HDU4790 Just Random 容斥原理,数学思路题

25 篇文章 0 订阅
10 篇文章 0 订阅

http://acm.hdu.edu.cn/showproblem.php?pid=4790

Just Random

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2985    Accepted Submission(s): 906


Problem Description
  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 <= 109, 0 <=c <= d <= 109, 0 <= m < p <= 109).
 

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
题意:在两个区间中各找一个数字,两个数字的和取余p=m;这样符合条件的概率是多少。

思路:分母很好算,区间长度乘积。分子分为3部分,先把区间分为两部分,一部分是长度p倍数的区间,剩下一部分是余下的不够长度p的区间。

举个栗子,任意一个数字都能在0,1,2中找到一个数字,使他们的和为3的倍数,和也可以是3的倍数加上一个余数。并且2,3,4也符合上面的结论,而且一定能找的一个且仅有一个。

这两个区间的整数部分很好算,重点是求两个余出的区间中匹配数量。

举个栗子。p=8,m=1

2,3,4,5,6(两个余下的区间,L区间)

0,1,2,3,4,5(R区间)

想个办法把区间变成这样

4,5,6

3,4,5(这样就能两两匹配了)

计算方法是:先找能与Lmax(L区间中最大数字匹配的数字。用x=Lmax-Rmin;看y=x-(p+m)的正负,y正的话说明Lmax太大了多了y个,把L区间的前y大删去,y负的话,说明Rmin太小了,把R区间前y小删去。

然后同理x=Rmax-Lmin;跟上面的完全相反,再删一遍之后就得到了4,5,6和3,4,5一一匹配。

因为p+m可能有多个值,比如m,m+2*p,m+3*p等等。y=x-(p+m)的情况很多,也可能是y=x-(2*p+m);解决方法在代码中有解释。虽然不知道什么是容斥原理,但我还是A了这道题,思路比较难想,但想到就能一遍过。

我比赛时的AC代码:

#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<cmath>
#include<cstring>
#define LL long long
using namespace std;
LL a1,a2,b1,b2,mod,p,la,lb,fenzi,fenmu,lam,lbm,aa1,aa2,bb1,bb2;
LL hg(LL r,LL rr,LL l,LL ll,LL k)//[r,rr],[l,ll],和为k
{
    LL flag1=rr-r+1;//r区间的长度
    LL flag2=ll-l+1;//l区间的长度
    LL x=ll+r;//ll区间的最大值加上r区间的最小值,跟k比较大小
    if(x>k) flag2-=(x-k);//重点是看这里是什么意思,减去后剩下的就是能匹配的
    if(x<=k) flag1-=(k-x);
    x=rr+l;//同上
    if(x>k) flag1-=(x-k);
    if(x<=k) flag2-=(k-x);
    if(flag1<=0||flag2<=0) return 0;//长度小于0,就不存在
    return flag1;
}
int main()
{
    int t;
    scanf("%d",&t);
    int cas=1;
    while(t--)
    {
        scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&a1,&a2,&b1,&b2,&mod,&p);
        la=a2-a1+1,lb=b2-b1+1;//la为第一个区间的长度,lb为第二个区间的长度
        lam=la%mod,lbm=lb%mod;//lam为取余剩的后的长度,lbm同理
        fenzi=0,fenmu=la*lb;
        fenzi+=lb*(la/mod);//答案的第一部分
        fenzi+=lam*(lb/mod);//答案的第二部分
        aa1=a1%mod+mod,aa2=aa1+lam-1;//将余下的长度转化成一个区间[aa1,aa2];区间里最大的数字小于mod*3,最小的数字大于等于mod*1.
        bb1=b1%mod+mod,bb2=bb1+lbm-1;//同上
        //答案的第三部分,求两个余下区间的匹配数量
        fenzi+=hg(aa1,aa2,bb1,bb2,mod*2+p);//两个区间最小的两个数和至少为mod*2
        fenzi+=hg(aa1,aa2,bb1,bb2,mod*3+p);
        fenzi+=hg(aa1,aa2,bb1,bb2,mod*4+p);
        fenzi+=hg(aa1,aa2,bb1,bb2,mod*5+p);
        fenzi+=hg(aa1,aa2,bb1,bb2,mod*6+p);//两个区间最大的两个数和最多为mod*6
        printf("Case #%d: ",cas++);
        if(fenzi==0)
            printf("0/1\n");
        else
            printf("%I64d/%I64d\n",fenzi/__gcd(fenzi,fenmu),fenmu/__gcd(fenzi,fenmu));
    }
}











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值