Just Random HDU - 4790
Coach Pang and Uncle Yang both love numbers. Every morning they play a game with number together. In each game the following will be done:
1. Coach Pang randomly choose a integer x in [a, b] with equal probability.
2. Uncle Yang randomly choose a integer y in [c, d] with equal probability.
3. If (x + y) mod p = m, they will go out and have a nice day together.
4. Otherwise, they will do homework that day.
For given a, b, c, d, p and m, Coach Pang wants to know the probability that they will go out.
Input
The first line of the input contains an integer T denoting the number of test cases.
For each test case, there is one line containing six integers a, b, c, d, p and m(0 <= a <= b <= 10 9, 0 <=c <= d <= 10 9, 0 <= m < p <= 10 9).
Output
For each test case output a single line “Case #x: y”. x is the case number and y is a fraction with numerator and denominator separated by a slash (‘/’) as the probability that they will go out. The fraction should be presented in the simplest form (with the smallest denominator), but always with a denominator (even if it is the unit).
Sample Input
4
0 5 0 5 3 0
0 999999 0 999999 1000000 0
0 3 0 3 8 7
3 3 4 4 7 0
Sample Output
Case #1: 1/3
Case #2: 1/1000000
Case #3: 0/1
Case #4: 1/1
题意:
给你a,b,c,d,p,m,随机等可能性的选择一对x,y,x∈[a,b],y∈[c,d],如果(x+y)%p=m,则称这次选择是成功的,问选择的成功率是多少。
分析:
现在真的是定式思维了,完全死了,一看到同余的就往数论想,看到同余就往线性方程扩展欧几里得想,看见解的个数就往gcd个数上想,看见gcd个数就往莫比乌斯反演上想,结果就死那里了,FUCK
这个题和数论没有半毛钱关系,就像是高中数学的线性规划
这位大佬博客讲的很明白了,具体的怎么做看这个吧
code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){
return b == 0 ? a : gcd(b,a%b);
}
int main(){
int T,cas = 0;
ll a,b,c,d,p,m,g;
ll k1,k2;
ll ans;
ll sum;
scanf("%d",&T);
while(T--){
ans = 0;
scanf("%lld%lld%lld%lld%lld%lld",&a,&b,&c,&d,&p,&m);
if((d - c) > (b - a)){//调整成x长y短的矩形
swap(a,c);
swap(b,d);
}
//第一种情况
if(a + c - m - 1 < 0)
k1 = (a + c - m - 1) / p;
else
k1 = (a + c - m - 1) / p + 1;
if(a + d - m < 0)
k2 = (a + d - m) / p - 1;
else
k2 = (a + d - m) / p;
ans += ((k1 * p + m - a - c + 1) + (k2 * p + m - a - c + 1)) * (k2 - k1 + 1) / 2;
//第二种情况
k1 = k2 + 1;
if(b + c - m < 0)
k2 = (b + c - m) / p - 1;
else
k2 = (b + c - m) / p;
ans += (k2 - k1 + 1) * (d - c + 1);
//第三种情况
k1 = k2 + 1;
if(b + d - m < 0)
k2 = (b + d - m) / p - 1;
else
k2 = (b + d - m) / p;
ans += ((b + d - k1 * p - m + 1) + (b + d - k2 * p - m + 1)) * (k2 - k1 + 1) / 2;
sum = (d - c + 1) * (b - a + 1);//总共的点
g = gcd(ans,sum);
sum /= g;
ans /= g;
printf("Case #%d: %lld/%lld\n",++cas,ans,sum);
}
return 0;
}