Four-tuples
Output
For each test case, output one line containing one integer, representing the answer.
Sample Input
1 1 1 2 2 3 3 4 4
Sample Output
1
Hint
Source
2018 Shandong ACM programing real contest, on-site problem replay
容斥原理!本来领导说省赛完之后要考离散的,结果还是没有复习离散书。。结果就GG了。。。
其实大概原理知道,但是没怎么用过,结果比赛时一紧张,就很emmm。。。
容斥原理最常见的一个就是用补集减。。结果当时比赛的时候想到是容斥原理了,
但是用的不是补集减做的,我是直接想用容斥,然后推了半天,没推出来,最后的一发,直接4区间乘积也没过,
很奇怪为什么我们的没有过。。不是说好的随便交就过吗qwq。。。
题解思路源自转载 链接 o#(这里、这里)#o
结果 = 总情况 - 总特殊情况
理解代码的时候注意交集和容斥的交集有区分,
也就是 答案=sum-(A∪B∪C∪D)
而(A∪B∪C∪D)=│A│+│B│+│C│+│D│
-│A∩B│-│A∩C│-│A∩D│-│B∩C│-│B∩D│-│C∩D│
+│A∩B∩C│+│A∩B∩D│+│A∩C∩D│+│B∩C∩D│
-│A∩B∩C∩D│(容斥原理)
假设A为第一种情况,B为第二种。。。。。
那么(易错点,这里容易弄混)A=(len(A∩B))*(r3 - l3 + 1)*(r4 - l4 + 1),B=。。。。
下面继续按惯例,贴别人的代码,
代码(别人的!有空自己会敲一遍)
#include<bits/stdc++.h> using namespace std; long long mo(long long x) { return x % ((long long)1e9 + 7); } long long jiao2(int l1, int r1, int l2, int r2) { long long ans = min(r1, r2) - max(l1, l2) + 1; if(ans <= 0) return 0; else return ans; } long long jiao3(int l1, int r1, int l2, int r2, int l3,int r3) { long long ans = min(r1, min(r2, r3)) - max(l1, max(l2, l3)) + 1; if(ans <= 0) return 0; else return ans; } long long jiao4(int l1, int r1, int l2, int r2, int l3,int r3, int l4, int r4) { long long ans = min(min(r1, r2), min(r3, r4)) - max(max(l1, l2), max(l3, l4)) + 1; if(ans <= 0) return 0; else return ans; } int main() { int l[8], r[8], t; long long sum; scanf("%d", &t); while(t--) { sum = 1; for(int i = 0; i < 4; i++) {h7 scanf("%d%d", &l[i], &r[i]); l[i + 4] = l[i]; r[i + 4] = r[i]; sum *= (r[i] - l[i] + 1); sum %= (long long)1e9 + 7; } // A + B + C + D 即一交集 for(int i = 0; i < 4; i++) { sum -= mo(mo(jiao2(l[i], r[i], l[i + 1], r[i + 1]) * (r[i + 2] - l[i + 2] + 1)) * (r[i + 3] - l[i + 3] + 1)); while(sum < 0) sum += (long long)1e9 + 7; } // A U B 即二交集 for(int i = 0; i < 4; i++) { sum += jiao3(l[i], r[i], l[i + 1], r[i + 1], l[i + 2], r[i + 2]) * (r[i + 3] - l[i + 3] + 1); sum %= (long long)1e9 + 7; } //二交集中 A U C, B U D sum += jiao2(l[0], r[0], l[1], r[1]) * jiao2(l[2], r[2], l[3], r[3]); sum %= (long long)1e9 + 7; sum += jiao2(l[1], r[1], l[2], r[2]) * jiao2(l[0], r[0], l[3], r[3]); sum %= (long long)1e9 + 7; // A U B U C == A U B U C U D 即三交集与四交集 sum -= mo(3 * jiao4(l[0], r[0], l[1], r[1], l[2], r[2], l[3], r[3]) ); while(sum < 0) sum += (long long)1e9 + 7; printf("%lld\n", sum); } return 0; }
自己敲了一遍
#include<bits/stdc++.h> using namespace std; typedef long long ll; const long long mod = 1e9+7; ll Mod(ll t){return t%mod;} ll jiao2(ll l1,ll r1,ll l2,ll r2) { ll ans=min(r1,r2)-max(l1,l2)+1; return ans>0?ans:0; } ll jiao3(ll l1,ll r1,ll l2,ll r2,ll l3,ll r3) { ll ans=min(r1,min(r2,r3))-max(l1,max(l2,l3))+1; return ans>0?ans:0; } ll jiao4(ll l1,ll r1,ll l2,ll r2,ll l3,ll r3,ll l4,ll r4) { ll ans=min(min(r1,r2),min(r3,r4))-max(max(l1,l2),max(l3,l4))+1; return ans>0?ans:0; } int main() { ll l[10],r[10]; int t; scanf("%d",&t); while(t--) { ll ans=1; for(int i=0;i<4;i++) { scanf("%lld %lld",&l[i],&r[i]); l[i+4]=l[i]; r[i+4]=r[i]; ans*=(r[i]-l[i]+1); ans%=mod; } for(int i=0;i<4;i++) { ans-=Mod( Mod( jiao2(l[i],r[i],l[i+1],r[i+1])*(r[i+2]-l[i+2]+1) )*(r[i+3]-l[i+3]+1)); while(ans<0)ans+=mod; } for(int i=0;i<4;i++) { ans+=Mod(jiao3(l[i],r[i],l[i+1],r[i+1],l[i+2],r[i+2])*(r[i+3]-l[i+3]+1)); ans%=mod; } ans+=Mod(jiao2(l[0],r[0],l[1],r[1])*jiao2(l[2],r[2],l[3],r[3])); ans%=mod; ans+=Mod(jiao2(l[0],r[0],l[3],r[3])*jiao2(l[1],r[1],l[2],r[2])); ans%=mod; ans-=(3*Mod(jiao4(l[0],r[0],l[1],r[1],l[2],r[2],l[3],r[3]))); while(ans<0)ans+=mod; printf("%lld\n",ans); } return 0; }