码迷,mamicode.com
首页 > 其他好文 > 详细

CodeForces 54C-First Digit Law(数位,概率dp)

时间:2015-08-17 23:21:37      阅读:228      评论:0      收藏:0      [点我收藏+]

标签:

题意:

给你n个区间,在每个区间里各取一个数(随机取),求这n个数中超过K%的数是首位为1数的概率

分析:

dp[i][j]取前i个数,有j个是首位为1的数的概率

易知,dp[i][j]=dp[i-1][j]*(1-p[i])+dp[i-1][j-1]*p[i];

现在关键是求p[i],第i个区间首位为1的数出现的概率,用数位统计一下即可

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <cctype>
#include <complex>
#include <cassert>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
#define lson l,m,rt<<1
#define pi acos(-1.0)
#define rson m+1,r,rt<<11
#define All 1,N,1
#define read freopen("in.txt", "r", stdin)
const ll  INFll = 0x3f3f3f3f3f3f3f3fLL;
const int INF= 0x7ffffff;
const int mod =  1000000007;
ll sum[20],a[20];
double dp[1010][1010],p[1010];
int bit[20],n,k;
void init(){
    sum[0]=1;
    for(int i=1;i<=20;++i)
        sum[i]=sum[i-1]*10;
}
ll countsum(int l){
    ll total=0;
    for(int i=0;i<=l;++i)
        total+=sum[i];
    return total;
}
//统计首位为1数的数量
ll countone(ll x){
    if(x==0)return 0;
    init();
    int len=0;
    while(x){
        bit[++len]=x%10;
        x/=10;
    }
    if(bit[len]>1){
        return countsum(len-1);
    }
    else{
        ll tmp=countsum(len-2);
        a[0]=0;
    for(int i=1;i<=len-1;++i)
        a[i]=a[i-1]+bit[i]*sum[i-1];
        tmp+=a[len-1]+1;
        return tmp;
    }
}
int main()
{
    ll l,r;
    while(~scanf("%d",&n)){
        for(int i=1;i<=n;++i){
            scanf("%I64d%I64d",&l,&r);
            ll tmp=countone(r)-countone(l-1);
            //cout<<tmp<<endl;
            p[i]=1.0*tmp/(r-l+1);
            //cout<<p[i]<<endl;
        }
        dp[1][1]=p[1];
        dp[1][0]=1.0-p[1];
        for(int i=2;i<=n;++i)
        for(int j=0;j<=i;++j){
            dp[i][j]+=dp[i-1][j]*(1.0-p[i]);
            if(j>0)
            dp[i][j]+=dp[i-1][j-1]*p[i];
        }
        scanf("%d",&k);
        double ans=0.0;
        for(int j=0;j<=n;++j)
            if(j>=(1.0*n*k/100))
                ans+=dp[n][j];
        printf("%.15lf\n",ans);
    }
return 0;
}

 

CodeForces 54C-First Digit Law(数位,概率dp)

标签:

原文地址:http://www.cnblogs.com/zsf123/p/4738032.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!