题意:

给你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;
}

 

转载于:https://www.cnblogs.com/zsf123/p/4738032.html

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐