HDU 4790 Just Random 【构造】

题目链接:传送门

题目大意:给你a, b, c, d, p and m(0 <= a <= b <= 109, 0 <=c <= d <= 109, 0 <= m < p <= 109).让你从 [a,
b] 中取出一个x,从[c, d] 中取出一个y,使得(x+y)(mod p)=m,求一共有多少种可能。

看见题目就想到了用构造的想法,讲解构造成二维坐标系,x+y=k*p+m是一条线,求这条线与构造的矩形(由点组成)一共有几个交点,这个矩阵也是有一定的规律的,虽然说数据量很大,但是其实就是三个数列,一个递增的一个相等的一个递减的,最后求出这三个数列的和即可。

根据上面的abcd所组成的矩形,其l1l2l3l4其实是一个递增的数列,直到等于b -a 递减也是一个道理。

很多细节处理的难点,本来说十分钟敲好的题目花了两小时+  坑队友了,其实是这样的,k1 k2 k3 k4  把这个图形分为三个部分,原来我都是一遍处理,k2就是k2,其实这样就出现很多难点,我们这样来想,k1k2在算第一段的时候算一次,k2k3在算第二段的时候算一次,k3k4在算第三段的时候算一次。这样就不会出现错误,还有就是最开始的时候,构造最初,我们把躺着的矩形也立起来,这样减少了要考虑的情况,使运算减少。

贴代码:

#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<stdio.h>
#include<cstdlib>
#include<functional>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define MAXN 110
#define eps 1e-7
#define INF 0x7FFFFFFF
#define seed 131
#define ll long long
#define ull unsigned ll
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

ll gcd (ll a,ll b)
{
    if(b==0) return a;
    else return gcd(b,a%b);
}
int main()
{
    ll a,b,c,d,p,m;
    int T;
    scanf("%d",&T);
    for(int ii=1; ii<=T; ii++)
    {
        scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&a,&b,&c,&d,&p,&m);
        ll ans=0;
        if(b-a > d-c)
        {
            ll tem;
            tem=a;a=c;c=tem;
            tem=b;b=d;d=tem;
        }
        ll t1,t2,add,sub,k1,k2,k3,k4;

         t1 =(a+c)%p;
         add=(m-t1+p)%p;
         k1 =(a+c+add-m)/p;
         t2 =(b+c-1)%p;
         sub=(t2-m+p)%p;
         k2 =(b+c-1-sub-m)/p;
         ans+=(k2-k1+1)*(1+add)+(k2-k1+1)*(k2-k1)/2*p;
        //printf("%I64d\n",ans);

        t1  =(b+c)%p;
        add =(m-t1+p)%p;
        k2  =(b+c+add-m)/p;
        t2  =(a+d)%p;
        sub =(t2-m+p)%p;
        k3  =(a+d-sub-m)/p;
        ans+=(k3-k2+1)*(b-a+1);
        //printf("%I64d\n",ans);

        t1  =(a+d+1)%p;
        add =(m-t1+p)%p;
        k3  =(a+d+1+add-m)/p;
        t2  =(b+d)%p;
        sub =(t2-m+p)%p;
        k4  =(b+d-sub-m)/p;
        ans+=(k4-k3+1)*(1+sub) + (k4-k3+1)*(k4-k3)/2*p;
        //printf("%I64d\n",ans);

        ll sum=(b-a+1)*(d-c+1);
        ll G = gcd(ans,sum);
        ans /= G;
        sum /= G;
        printf("Case #%d: %I64d/%I64d\n",ii,ans,sum);
    }
    return 0;
}

赛后看了看有一种方法也挺好,用了容斥的原理,ans = gt(b, d) - gt(a - 1, d) - gt(b, c - 1) + gt(a - 1, c - 1);

gt(a, b)表示的是0-a, 和0-b两个区间中满足题意的解的对数。

传送门

HDU 4790 Just Random 【构造】

时间: 2024-12-23 14:44:05

HDU 4790 Just Random 【构造】的相关文章

hdu 4790 Just Random 神奇的容斥原理

1 /** 2 大意: 给定[a,b],[c,d] 在这两个区间内分别取一个x,y 使得 (x+y)%p = m 3 思路:res = f(b,d) -f(b,c-1)-f(a-1,d)+f(a-1,c-1); f(b,d ) 表示在[0,b],[0,d] 之间有多少个符合上述要求的数 4 1.将[0,b] 分为两部分, b/p 和 b%p 能整除p的[0,(b/p)*p] 和[(b/p)*p+1,b ] 同理[0,d]也可以这样分, 这样对于[0,b] [0,d ] 分别有两种情况,则一共有四

HDU - 4790 Just Random

题意:求从[a,b],[c,d]两个区间找到两个数使得他们的和%p=m,求概率 思路:我们想办法把区间的左范围化到0,那么结果就相对好弄了,应用容斥原理比直接解答问题简单点,假设f(a,b)是区间[0,a],[0,b]中满足条件的个数,设p=6.m=2 那么第一个区间可以看成 : A=[0,1,2,3,4,5]+[0,1,2,3,4,5]+..... B= (0,1,2,3,4) 第二个区间可以看成:C=[0,1,2,3,4,5]+....D=(0,1) 那么题目就可以看成:A+C,A+D, B

HDU 4790 Just Random 数学

链接:pid=4790">http://acm.hdu.edu.cn/showproblem.php?pid=4790 意:从[a.b]中随机找出一个数字x,从[c.d]中随机找出一个数字y.给出p.m,假设(x+y)%p==m则算成功,问成功的概率是多少. 思路:[a.b]中连续p个数.[c,d]中连续p个数.用这2*p个数进行组合能找到p种的成功组合(详细不证),所以找到[a.b]中p循环的个数x1,[c,d]中p循环的个数y1,则它们组成的成功组合数为p*x1*y1. 然后是处理边界

hdu - 4790 - Just Random(容斥 + 组合数学)

题意:在 [a, b] 取一个整数 x,在 [c, d] 取一个整数 y,求满足 (x + y) % p = m 的 (x, y) 的对数(0 <= a <= b <= 10 ^ 9, 0 <=c <= d <= 10 ^ 9, 0 <= m < p <= 10 ^ 9). 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4790 -->>2013年成都区赛最后一题,当时TLE6次无果....加

hdu 4790 Just Random 容斥原理+数学

Just Random Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1723    Accepted Submission(s): 483 Problem Description Coach Pang and Uncle Yang both love numbers. Every morning they play a game w

hdu 4790 Just Random (2013成都J题) 数学思路题 容斥

题意:在[a,b]  [c,d] 之间,和模p等于m的对数 详见代码 1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include<cmath> 5 #define LL long long 6 using namespace std; 7 int T; 8 LL a,b,c,d,p,m; 9 10 LL gcd(LL a, LL b) { 11 return b ?

hdu 4790 Just Random (思路+分类计算+数学)

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 r

HDU 4961 Boring Sum 构造题

用一个数组c, c[i]表示i这个数出现的最近数字是几. 那么当加入一个6,则 c[1] = c[2] = c[3] = c[6] = 6; ==最近怎么都要开挂啊.. #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N = 100005; inl

hdoj 4790 Just Random 【数学】

题目:hdoj 4790 Just Random 题意:给你两个闭区间[a,b],[c,d],分别从中等可能的跳出 x 和 y ,求(x+y)%p == m的概率 分析: 假如是[3,5] [4,7]   p = 2 , m = 1: 则所有的和 7 8 9 10 8 9 10 11 9 10 11 12 1 2 3 3 2 1 后面一行出现次数,可以发现可以分成三部分,第一部分递增的等差数列,第二部分值都相等,第三部分等差数列 然后用等差数列求和公式求和就ok AC代码: #include<i