题意:给出两个区间[a,b],[c,d],各取一个数i,j,求能使(i+j)%p=m的概率
思路:总体可以取的数个数为(b-a+1)*(d-c+1),计算能满足条件的个数,如果列出来会发现会形成一个平行四边形,只要保证a+d>b+c时就可以把这个平行四边形分成三部分,然后分开找满足(i+j)%p=m的位置就可以了
完整代码:
#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
typedef long long LL;
LL a,b,c,d,p,m;
long long gcd(long long a,long long b)
{
if(b==0) return a;
else gcd(b,a%b);
}
int main()
{
LL t;
scanf("%lld",&t);
LL cnt=0;
while(t--)
{
cnt++;
LL ans=0;
LL a,b,c,d,p,m;
scanf("%lld%lld%lld%lld%lld%lld",&a,&b,&c,&d,&p,&m);
if((a+d)<(b+c))
{swap(a,c);swap(d,b);}
LL n=b-a+1;
LL next1,pre1;
if(m>=(a+c)%p) next1=m-(a+c)%p;
else next1=m-(a+c)%p+p;
if((b+c-1)%p>=m) pre1=(b+c-1)%p-m;
else pre1=(b+c-1)%p-m+p;
if(pre1<=b-a-1&&next1<=b-a-1)
ans+=((1+next1)+(b-a-pre1))*(b-a-pre1-next1-1+p)/p/2;
LL next2,pre2;
if(m>=(a+d+1)%p) next2=m-(a+d+1)%p;
else next2=m-(a+d+1)%p+p;
if((b+d)%p>=m) pre2=(b+d)%p-m;
else pre2=(b+d)%p-m+p;
if(pre2<=b-a-1&&next2<=b-a-1)
ans+=((1+pre2)+(b-a-next2))*(b-a-pre2-next2-1+p)/p/2;
LL next3,pre3;
if(m>=(b+c)%p) next3=m-(b+c)%p;
else next3=m-(b+c)%p+p;
if((a+d)%p>=m) pre3=(a+d)%p-m;
else pre3=(a+d)%p-m+p;
LL num=a+d-b-c+1;
if(pre3<num&&next3<num)
ans+=n*(b-a+num-pre3-(b-a+1+next3)+p)/p;
LL sum=(b-a+1)*(d-c+1);
LL g=gcd(ans,sum);
ans/=g;
sum/=g;
cout<<"Case #"<<cnt<<": "<<ans<<"/"<<sum<<endl;
}
}