HDU 4790 Just Random

Just Random

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


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

Source

题目的意思是,在[a,b]随机取一个数,在[c,d]中随机取一个数,如果这两个数的和%p==m,就是符合条件的,求所有符合条件的情况在所有情况中的比值。
解法:
两个区间的取值可以看成是:
a+c+0 a+c+1 a+c+2 ...... a+d
a+1+c+0 a+1+c+1 ..............a+1+d
...........................................................
..................................................................
b+c ..........................................................b+d
显然可以看成三个区域,左边和右边是等差数列。

需要注意的是要弄清楚怎么取在这个范围内的%P==m的点。注意ADD和SUB的写法。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>
using namespace std;
long long gcd(long long a,long long b)
{
	return b==0? a:gcd(b,a%b); 
} 
int main()
{
	long long T,g=1;
	cin >> T;
	while(T--)
	{
		long long a,b,c,d,p,m;
		cin >> a >> b >> c >> d >> p >> m;
		long long s1 = b-a+1;
		long long s2 = d-c+1;
		if(s1>s2)
			swap(s1,s2),swap(a,c),swap(b,d);
		
		long long t1,t2,cnt1,cnt2,add,sub,ans=0;
		//left
		t1 = (a+c)%p;
		add = (m-t1+p)%p;
		cnt1 = (a+c+add-m)/p;//这里是根据公式换算。(a+c+add) = m+(p*cnt1); 
		t2 = (b+c-1)%p;
		sub = (t2-m+p)%p;
		cnt2 = (b+c-1-sub-m)/p;
		ans+= (cnt2-cnt1+1)*(add+1)+(cnt2-cnt1+1)*(cnt2-cnt1)*p/2;
		//mid
		t1 = (b+c)%p;
		add = (m-t1+p)%p;
		cnt1 = (b+c+add-m)/p;
		t2 = (a+d)%p;
		sub = (t2-m+p)%p;
		cnt2 = (a+d-sub-m)/p;
		ans+= (cnt2-cnt1+1)*(b-a+1);
		//right
		t1 = (a+d+1)%p;
		add = (m-t1+p)%p;
		cnt1 = (a+d+1+add-m)/p;
		t2 = (b+d)%p;
		sub = (t2-m+p)%p;
		cnt2 = (b+d-sub-m)/p;
		ans+= (cnt2-cnt1+1)*(sub+1)+(cnt2-cnt1+1)*(cnt2-cnt1)*p/2;
		//cout<<ans<<endl; 
		long long total = s1*s2;
		long long cd = gcd(total,ans); 
		ans = ans/cd;
		total = total/cd; 
		printf("Case #%lld: %lld/%lld\n",g++,ans,total);
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值