题目链接:
http://codeforces.com/contest/621/problem/C
题目大意:
有n 个区间,每个区间可以等概率的选择一个数,如果某个区间上选的数和他相邻区间选的数的乘积能够整除素数p,那么就可以得到2000块。现在问得到钱的期望值。
范围:n<=100000。
思路:
如果两个数乘积是素数p的倍数,那么这两个数里面只要有一个数是素数即可。
所以对于区间1和区间2,我就可以统计出区间1里面能整除p 的个数 t1,此时sum=t1*(r[2]-l[2]+1);同理,统计出区间2上面的个数t2,就有sum+=t2*(r[1]-l[1]+1),但是这中间有重复,所以要减去t2*t1。除以总的情况数,这样就能够算出两个相邻区间上的概率了。累加即可得到总的概率,最后乘上2000。
代码:
#include<stdio.h>
#include<string.h>
#define ll __int64
ll temp;
ll l[100005],r[100005],x[100005];
int main()
{
int n,p,i,j,k;
double ans;
while(~(scanf("%d%d",&n,&p)))
{
memset(x,0,sizeof(x));
for(i=1;i<=n;i++)
{
scanf("%I64d%I64d",&l[i],&r[i]);
x[i]=r[i]/p-l[i]/p;
if(l[i]%p==0)x[i]++; //统计区间上面能够整除p 的个数
// printf("%I64d\n",x[i]);
}
ans=0;
for(i=1;i<n;i++)
{
temp=(x[i]*(r[i+1]-l[i+1]+1)+x[i+1]*(r[i]-l[i]-x[i]+1));
// printf("%.2f\n",temp);
ans+=temp/((r[i]-l[i]+1)*(r[i+1]-l[i+1]+1)*1.0);
}
temp=(x[n]*(r[1]-l[1]+1)+x[1]*(r[n]-l[n]-x[n]+1));
ans+=temp/((r[1]-l[1]+1)*(r[n]-l[n]+1)*1.0);
printf("%.7f\n",ans*2000);
}
}