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 }