首先,我们一定要求出每个[l,r]内的满足条件的数的个数,方法也很简单,一位一位算就好了,具体可以看我的代码。
然后就可以求出在每一个袋子里抓球是否是1的概率了。
然后考虑如何求题目中的问题。
然后发现那个k%其实就是n*k/100,这个值不会超过n。
然后就可以很容易的设计出一种状态来进行dp,
设f(i,j)代表前i个袋子中有j个是1的概率
设我们前面求出的抓1的概率为pi
则dp方程就是f(i,j)=f(i−1,j)∗(1−pi)+f(i−1,j−1)∗pi
边界就是f(0,0)=1
然后直接dp,没什么问题了。
统计答案就是统计
∑ni=n∗k/100f(n,i)
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstdlib>
#define ll long long
using namespace std;
inline int read(){
int x=0;char ch=' ';int f=1;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
ll getcnt(ll x){
if(x<=0)return 0;
if(x>=1&&x<=9)return 1;
ll wei=0;
ll now=1;
while(x>=now){
wei++;
now*=10;
}
ll ans=1;
now=1;
for(int i=2;i<wei;i++){
now*=10;
ans+=now;
}
now*=10;
if(x/now!=1){
ans+=now;
}
else ans+=x-now+1;
return ans;
}
int n,k;
ll l[2001],r[2001];
ll cnt[2001];
long double a[2001];
long double f[2001][2001];
int main(){
freopen("chance.in","r",stdin);
freopen("chance.out","w",stdout);
n=read();k=read();
for(int i=1;i<=n;i++){
scanf("%I64d %I64d",&l[i],&r[i]);
cnt[i]=getcnt(r[i])-getcnt(l[i]-1);
a[i]=(double)cnt[i]/(double)(r[i]-l[i]+1);
}
f[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=i;j++){
if(j>0)f[i][j]+=f[i-1][j-1]*a[i];
f[i][j]+=f[i-1][j]*(1.0-a[i]);
}
}
double lim=(double)n*(double)k/100.0;
long double ans=0;
for(int i=n;i>=lim;i--){
ans+=f[n][i];
}
printf("%.12Lf",ans);
return 0;
}