题意:
给你a,b,c,d,p,m,从区间[a,b]任意选一个数x从区间[c,d]任意选一个数y满足(x+y)%p= m 的概率是多少
方法:
对[a,a],[c,d]: 可以快速算出至少有(d-c+1)/m 个满足条件的x.y
同理对[a,b][c,d]可以得到至少有(b-a+1)*(d-c+1)/m个
对[a,a][c,d]区间还剩下t= (d-c+1)%m 个数没有计算,区间[a,b][c,d]就还剩下(b-a+1)*t个数没讨论,然后我们根据每个区间%m的第一个数会呈现0,1,2,3,4,5,6,7,,m-1,0,1的变化去统计即可
PS:
我说不清楚。。。 表达能力有限
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define LL __int64 LL gcd(LL a, LL b) { return b== 0? a: gcd(b, a%b); } int main() { // freopen("in.txt","r",stdin); int T; scanf("%d",&T); for(int C= 1; C<= T; C++) { LL a, b, c, d, p, m; scanf("%I64d %I64d %I64d %I64d %I64d %I64d", &a, &b, &c, &d, &m, &p); LL ans= (d- c+ 1)/m; ans*= (b- a+ 1); int t= (d- c+ 1)%m; //首个数 // printf("%I64d\n", ans); if(t) ans+= ((b- a+ 1)/m)*(t); // printf("%I64d\n", ans); int xx= (b- a+ 1)%m; //int xx= (d- c+ 1)%m; int num= (a + c)%m; int z; // printf("num= %d p= %d\n",num, p); if(num<= p) z= p- num; else z= (p+1)+ (m- 1- num); // printf("%d %d\n",z,xx); if(z+1>= xx) { int ll= z-xx+1, rr= z; ll++, rr++; // printf("%d %d\n", ll,rr); if(t>= ll) { if(t>= rr) ans+= rr- ll +1; else ans+= t- ll +1; } } else { int ll= 0, rr= z; ll++, rr++; // printf("%d %d %d\n",ll,rr,t); if(t>= rr) ans+= rr- ll+1; else ans+= t- ll+1; xx-= z+1; ll= (m-1)-xx+1, rr= m-1; ll++, rr++; // printf("%d %d %d\n",ll,rr,t); if(t>= ll) { if(t>= rr) ans+= rr-ll+1; else ans+= t-ll+1; } } // printf("%I64d\n",ans); printf("Case #%d: ",C); if(ans== 0) printf("0/1\n"); // printf("0\n"); else { LL sum= (d-c+1)*(b-a+1); LL g= gcd(ans,sum); printf("%I64d/%I64d\n",ans/g,sum/g); // printf("%lf\n",1.0*ans/sum); } } return 0; }