2013成都站J题||hdu4790 数论

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

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 <= 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]和[b,c]两个区间内各取一个数,有多少取法可以满足(x+y)%p==m,求所占的比例。

解题思路:

               说实话自己真不会写,看题解也是不知所云。正好去年参加现场赛的学长昨天从百度实习回来了,经他一点播,奋斗了几个小时终于写出来了,瞬间感觉对数论的简单处理又上升了一个等级。

我们先把区间[a,b] [c,d]变为[a+p-m,b+p-m]和[c,d],这样一来题目就变成了求在区间[a+p-m,b+p-m]和[c,d]内各取一个数,有多少取法可以满足(x+y)%p==0,求所占的比例。

我们够着一个平行四边形枚举出所有的情况数;

              a+c  a+c+1  a+c+2   ..................a+d
                      a+c+1  a+c+2  a+c+3 ........a+d  a+d+1
                                   a+c+2  a+c+3         a+d   a+d+1   a+d+2
                                                            ....................
                                                                ...................
                                                   b+c   b+c+1   ...............................................b+d; 


上面大致形成一个斜的矩阵。
使用b+c  和 a+d两条竖线,就可以分成三部分。前后两部分个数是等差数列,中间个数是相等的。

根据a+d和b+c的大小关系分两种情况讨论。给定两个例子:我的电脑画图本事不是很好,手写一个了

ac

代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
// #define debug
using namespace std;

typedef long long LL;

LL gcd(LL x,LL y)
{
    if(y==0)
        return x;
    return gcd(y,x%y);
}
LL a,b,c,d,p,m;
int main()
{
    int T,tt=0;
    scanf("%d",&T);
    while(T--)
    {
       scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&a,&b,&c,&d,&p,&m);
       LL y=(b-a+1)*(d-c+1);
       a+=p-m;///转化为模p为0
       b+=p-m;
       #ifdef debug
       printf("a b c d:%I64d %I64d %I64d %I64d\n",a,b,c,d);
       #endif // debug
       LL ans=0;
      /**情况1:  ________
                 \_______\
       **/
       if(c+b<=a+d)
       {
            ///左半部分
            LL cnt_start=a+c+(p-(a+c)%p)%p;
            LL cnt_end=b+c-1-(b+c-1)%p;
            LL a1=(p-(a+c)%p)%p+1;
            LL n=(cnt_end-cnt_start)/p+1;
            ans+=a1*n+p*n*(n-1)/2;

            ///右半部分
            cnt_end=b+d-(b+d)%p;
            cnt_start=a+d+(p-(d+a)%p)%p;
            a1=(b+d)%p+1;
            n=(cnt_end-cnt_start)/p+1;
            ans+=a1*n+p*n*(n-1)/2;

            /// 中间部分
            cnt_end=a+d-1-(a+d-1)%p;
            cnt_start=b+c+(p-(b+c)%p)%p;
            if(cnt_start>cnt_end)
                n=0;
            else
                n=(cnt_end-cnt_start)/p+1;
            a1=b-a+1;
            ans+=a1*n;

       }
       /**情况2:__
                \ \
                 \ \
                  \ \
                   \ \
                    \_\
        **/
       else
       {
            ///左半部分
            LL cnt_start=a+c+(p-(a+c)%p)%p;
            LL cnt_end=a+d-(a+d)%p;
            LL a1=(p-(a+c)%p)%p+1;
            LL n=(cnt_end-cnt_start)/p+1;
            ans+=a1*n+p*n*(n-1)/2;

            ///右半部分
            cnt_start=b+c+(p-(b+c)%p)%p;
            cnt_end=b+d-(d+b)%p;
            a1=(b+d)%p+1;
            n=(cnt_end-cnt_start)/p+1;
            ans+=a1*n+p*n*(n-1)/2;

            /// 中间部分
            cnt_start=a+d+1+(p-(a+d+1)%p)%p;
            cnt_end=b+c-1-(b+c-1)%p;
            if(cnt_start>cnt_end)
                n=0;
            else
                n=(cnt_end-cnt_start)/p+1;
            a1=d-c+1;
            ans+=a1*n;
            #ifdef debug
            LL cnt=a1*n+p*n*(n-1)/2;
            printf("%I64d ???? %I64d\n",cnt_start,cnt_end);
            printf("%I64d %I64d %I64d=cnt\n",a1,n,cnt);
            #endif // debug
       }
       printf("Case #%d: %I64d/%I64d\n",++tt,ans/gcd(y,ans),y/gcd(y,ans));
    }
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值