J - Just Random HDU - 4790 (几何概率,数形结合)

题目: http://acm.hdu.edu.cn/showproblem.php?pid=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, 0 <= c <= d <= 10, 0 <= m < p <= 10).

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).

把可能性转化成矩形的点即可,然后取每一条可能的线求出线上的点数和就是符合条件的点。。。

细节问题要细节;

ac代码:

#include <cstdio>
#include <math.h>
#include <algorithm>
#include <cstring>
#include <queue>
#include <iostream>
#define inf 0x3f3f3f3f
#define exp 0.00000001
#define lc d<<1
#define rc d<<1|1
#define mid ((l+r)>>1)

using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int mx = 5e2+100;
ll a, b, c, d, m, p;
int quj(ll k) {///判断线在哪个部分
    ll x = -c+m+k*p;
    if (x >= a &&x <= a+d-c) return 1;
    if (x <= b && x > a+d-c) return 2;
    if (x > b && x <= b+d-c)
        return 3;
    return 0;
}

void cmp() {///交换
    if (b-a+1 < d-c+1) {
        swap(a, c);
        swap(b, d);
    }
}

void solve() {///解决问题
    ll sum = 0, pp = (b-a+1)*(d-c+1);
    ll k2 = (a+d-m)/p, k1 = ceil((a+c-m*1.)/p);
    ll st, numk;
    if (a+c < m) k1 = 0;
    if (a+d < m) k2 = -1;
//    printf("%lld\n", k1);
    if (quj(k1) == 0) {
        puts("0/1");
        return;
    }

    if (k2 >= k1) {
        numk = k2-k1;
        st = -c+m+k1*p-a+1;
        sum += st;
        sum += numk*st+numk*(numk+1)/2*p;
        k2++;
    }
    else k2 = k1;
//    printf("1 --- %lld %lld\n", st, c);
//    printf("1 --- %lld\n", sum);
    if (quj(k2) == 2) {
        k1 = k2;
        k2 = (b+c-m)/p;
        numk = k2-k1+1;
        sum += numk*(d-c+1);
        k2++;
    }
    if (quj(k2) == 3) {
        k1 = k2;
        k2 = (b+d-m)/p;
//        printf("%lldssss \n", k2);
        numk = k2-k1;
        st = d-(-b+m+k2*p)+1;
        sum += st;
        sum += numk*st+numk*(numk+1)/2*p;
        k2++;
    }
//    printf("2 --- %lld %lld\n", sum, pp);
    printf("%lld/%lld\n", sum/__gcd(pp, sum), pp/__gcd(pp, sum));

}

int main () {
    int T;
    #ifndef ONLINE_JUDGE
    freopen("hcl.in","r",stdin);
    freopen("hcl.out","w",stdout);
    #endif
    scanf("%d", &T);
    for (int o = 1; o <= T; ++o) {
        printf("Case #%d: ", o);
        scanf("%lld%lld%lld%lld%lld%lld", &a, &b, &c, &d, &p, &m);
        cmp();
        solve();
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值