https://codeforces.com/problemset/problem/621/C
思路:
首先转化成倍数问题。区间为p的倍数O(1)便可得出。
暴力的话肯定不行。
考虑相邻一对 对答案的贡献。
设c1,c2为相邻一对中p的倍数的个数。
x1,x2...xn为每个区间的总共能取的个数
单纯考虑c1,c2对答案的贡献
可以得出 [ c1*c2+c1*(x2-c2)+c2*(x1-c1) ] *x3*x4*x5...xn /( x1*x2*x3*x4....) 所有相邻对的贡献就是在分子后面加各自式子。
但是你发现题没有mod。还要对这个式子拆分。
变成了 [ c1*c2+c1*(x2-c2)+c2*(x1-c1) ] /(x1*x2) ;
至少一个转化成没有
(x1-c1)*(x2-c2)/(x1*x2)===(x1-c1)/c1 * (x2-c2)/x2,然后就变成了除法的概率了。
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e5+1000;
typedef long long LL;
inline LL read(){LL x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
double p[maxn];///每个含p倍数的概率
int main(void)
{
cin.tie(0);std::ios::sync_with_stdio(false);
LL n,pri;cin>>n>>pri;
for(LL i=1;i<=n;i++){
LL l,r;cin>>l>>r;
LL len=r-l+1;
p[i]=1.0*(r/pri-(l-1)/pri )/( 1.0*len );
}
p[n+1]=p[1];
double ans=0;
for(LL i=1;i<=n;i++){
ans+=( 1.0-(1.0-p[i])*(1.0-p[i+1]) )*2000.0;
}
printf("%.8f\n",ans);
return 0;
}