Hdu--4790(容斥原理)

2014-11-07 13:56:56

思路:这题用了容斥原理考虑,然后就是细节处理了。

  方法:把答案写成:F(b,d) - F(a - 1,d) - F(b,c - 1) + F(a - 1,c - 1),F(x,y)的含义是从[0,x],[0,y]中选两个数使得他们的和模p等于m的方案数。

  (1)处理F(x,y),首先把区间内的数全部模p,我们发现会形成: 0,1,2,....,p-1,0,1,2,...,p-1,0,1,...,然后把0,1,2,...,p-1划为一个区间(成为完整区间),可以发现两个{0,1,2,...,p-1}可以形成p对匹配使得每对匹配的两个数满足条件(也就是一个区间内所有数都能在另一个区间内找到匹配数),于是我们把[0,x]和[0,y]中所有完整区间找出来(数目:nx,ny),剩下来两个不完整的区间:[?,x],[?,y],然后我们可以把所取的完整区间右移(可以证明每个完整区间内的元素数不变,且各个相异),这样不完整区间变为:[0,tx],[0,ty]。

  (2)处理不完整区间:[0,tx],[0,ty],(tx < p,ty < p),分成两部分处理:[0,m],[m+1,?],为什么呢,其实在前面证明完整区间内数都能匹配时就能发现:[0,m]的数在另一个区间内的匹配数也在[0,m]范围内,而[m+1,?]内数在另一区间内匹配数在[m+1,?]内,所以只要分两部分分别找出来即可。(有些细节处理见代码把。。。这题题不太清楚QAQ,我觉得没有画图实在不好搞,以后这种题目一定要细心,十分考验代码和思维!)

 1 /*************************************************************************
 2     > File Name: 4790.cpp
 3     > Author: Nature
 4     > Mail: 564374850@qq.com
 5     > Created Time: Fri 07 Nov 2014 12:03:57 AM CST
 6 ************************************************************************/
 7 
 8 #include <cstdio>
 9 #include <cstring>
10 #include <cstdlib>
11 #include <cmath>
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include <stack>
16 #include <queue>
17 #include <iostream>
18 #include <algorithm>
19 using namespace std;
20 #define lp (p << 1)
21 #define rp (p << 1|1)
22 #define getmid(l,r) (l + (r - l) / 2)
23 #define MP(a,b) make_pair(a,b)
24 typedef long long ll;
25 const int INF = 1 << 30;
26 
27 int T;
28 ll a,b,c,d,p,m;
29 
30 ll Gcd(ll a,ll b){
31     return b == 0 ? a : Gcd(b,a % b);
32 }
33 
34 ll F(ll x,ll y){
35     if(x < 0 || y < 0)
36         return 0;
37     ll nx = (x + 1) / p,tx = (x + 1) - nx * p - 1;
38     ll ny = (y + 1) / p,ty = (y + 1) - ny * p - 1;
39     ll res = nx * ny * p + (tx + 1) * ny + (ty + 1) * nx;
40     ll ex = tx - m > 0 ? tx - m : 0,ey = ty - m > 0 ? ty - m : 0;
41     tx -= ex;
42     ty -= ey;
43     ll l1,l2;
44     if(tx >= 0 && ty >= 0){
45         l1 = tx - (m - ty) + 1;
46         l2 = ty - (m - tx) +1;
47         if(l1 >= 0 && l2 >= 0){
48             res += max(l1,l2);
49         }
50     }
51     if(ex > 0 && ey > 0){
52         ex += m;
53         ey += m;
54         l1 = ex - (p + m - ey) + 1;
55         l2 = ey - (p + m - ex) + 1;
56         if(l1 >= 0 && l2 >= 0){
57             res += max(l1,l2);
58         }
59     }
60     return res;
61 }
62 
63 int main(){
64     scanf("%d",&T);
65     for(int Case = 1; Case <= T; ++Case){
66         scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&a,&b,&c,&d,&p,&m);
67         printf("Case #%d: ",Case);
68         ll ans = F(b,d) - F(a - 1,d) - F(b,c - 1) + F(a - 1,c - 1);
69         ll den = (b - a + 1) * (d - c + 1);
70         ll g = Gcd(ans,den);
71         printf("%I64d/%I64d\n",ans / g,den / g);
72     }
73     return 0;
74 }

 

posted @ 2014-11-07 14:15  Naturain  阅读(186)  评论(0编辑  收藏  举报