hdu 4790 Just Random 2013 Asia Chengdu Regional Contest [数学]【思维】

68 篇文章 0 订阅
27 篇文章 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): 2782 Accepted Submission(s): 850

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

Source
2013 Asia Chengdu Regional Contest

—————————–.

题目大意:
给你两个区间[a,b][c,d]
求分别从两个区间中取出x,y. 使得(x+y)mod p==m的概率

解题思路 :

概率就是
可行的组数/所有的组数
所有的组数就是(b-a+1)*(d-c+1)

问题就是怎么求解可行的组数
如果暴力的话 最坏是O(10^18) 一定会超时
如果把区间对p取模 存在数组里然后在选取 时空复杂度均为O(10^9) 还是不可行

于是 就改变一下思路
他要求的是(x+y)mod p==m 那么x+y的区间就是
[a+c,b+d]

这样的话 会发现 [a+c,b+d]中每个数出现的次数虽然不相等但是有非常严谨的规律 如下图
这里写图片描述

明确这些就很好算了

只有分别对这三个区间进行统计就行了

但是为了方便计算这里讲[c,d]区间变成了[c+p-m,d+p-m]
这样的话选出来的数就相当于(x+y)mod p==0
统计的时候就方便多了

统计的时候
每一个区间只要找到最大和最小的满足mod p==0的数的位置
然后用高斯公式就能直接计算了 ::(首项+末项)*项数/2

为了避免重复统计 鄙渣做了2点改动
1.判断的区间为[A1,A2] (A2,A3) [A3,A4]
2.特判了一下(a==b&&c==d)的情况 否则按照我的思路就会多统计一遍

    if(a==b&&c==d)
    {
        if((a+c)%p==m)
            printf("Case #%d: 1/1\n",++kase);
        else
            printf("Case #%d: 0/1\n",++kase);
        continue;
    }

附本题代码
—————————.

#include <bits/stdc++.h>

using namespace std;
typedef long long int LL;
/*************************/
LL gcd(LL a,LL b)
{
    if(!b) return a;
    else return gcd(b,a%b);
}
int num1[100050];
int num2[100050];

int main()
{
    int _,kase;
    while(~scanf("%d",&_))
    {
        kase=0;
        while(_--)
        {
            LL a,b,c,d,p,m;
            scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&a,&b,&c,&d,&p,&m);
            //
            if(a==b&&c==d)
            {
                if((a+c)%p==m)
                    printf("Case #%d: 1/1\n",++kase);
                else
                    printf("Case #%d: 0/1\n",++kase);
                continue;
            }
            //
            if(m)c+=p-m,d+=p-m;
            LL sum = 0;

            LL a1=a+c,a2=a+d,a3=b+c,a4=b+d;

            int flag = 0;
            if(a2>a3)
            {
                swap(a2,a3);
                flag=1;
            }
            int da,xi;

            //a1,a2
            xi=a1/p,da=a2/p;
            if(xi*p<a1)    xi++;
            if(da*p>a2)    da--;
            if(da>=xi&&a1<=xi*p&&xi*p<=a2&&a1<=da*p&&da*p<=a2)
            {
                sum+=(da-xi+1)*(xi*p-a1+1+da*p-a1+1)/2 ;
            }
            //printf("%I64d %I64d\n",da*p,xi*p);
            //printf("%I64d\n",sum);

            //a2,a3
            xi=a2/p,da=a3/p;
            if(xi*p<=a2)    xi++;
            if(da*p>=a3)    da--;
            if(da>=xi&&a2<=xi*p&&xi*p<=a3&&a2<=da*p&&da*p<=a3)
            {
                sum+=(da-xi+1)*(a2-a1+1) ;
            }
            //printf("%I64d\n",sum);
            //a3,a4
            xi=a3/p,da=a4/p;
            if(xi*p<a3)    xi++;
            if(da*p>a4)    da--;
            if(da>=xi&&a3<=xi*p&&xi*p<=a4&&a3<=da*p&&da*p<=a4)
            {
                sum+=(da-xi+1)*(a4-xi*p+1+a4-da*p+1)/2 ;
            }

            //printf("%I64d\n",sum);

            /****************************/
            LL fenzi = sum;
            LL fenmu = (b-a+1)*(d-c+1);

            LL tem = gcd(fenzi,fenmu);
            //printf("%I64d %I64d  %I64d\n",fenzi ,fenmu,tem);
            printf("Case #%d: %I64d/%I64d\n",++kase,fenzi/tem,fenmu/tem);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值