Just Random HDU - 4790(数学+数形结合)

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;
}

猜你喜欢

转载自blog.csdn.net/codeswarrior/article/details/82457736
今日推荐