山東省第九屆ACM F-Four-tuples(容斥定理)
阿新 • • 發佈:2018-12-24
Given ,please count the number of four-tuples such thatand
The answer should modulo109+7 before output.
輸入描述:
The input consists of several test cases. The first
line gives the number of test cases,T(1≤T≤106).
For each test case, the input contains one line
with 8 integers,.
輸出描述:
For each test case, output one line containing one integer, representing the answer.
示例1
輸入
1
1 1 2 2 3 3 4 4
輸出
1
(聽說這套題AC5道就穩金了,,,)
題目大意:給出4個區域,每個區域取一個數,求可取的種數。要求
思路:區間有可能互相重疊,所以考慮容斥定理。(只是名字高階而已)所有區域值相乘為總的方案數,需要減去特殊情況下的方案。理一下思路,4個條件為4種事件,那就可能1.2 。1.3 。 1.4。 2.3。 2.4。 3.4。 1.2.3。 1.2.4。 1.3.4。 2.3.4。 1.2.3.4。相交總共11種特殊情況,依次減去即可。(和模擬題一樣煩)
程式碼如下:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7; ll l1,r1,l2,r2,l3,r3,l4,r4; int main() { int T; scanf("%d",&T); while(T--) { scanf("%lld%lld%lld%lld%lld%lld%lld%lld",&l1,&r1,&l2,&r2,&l3,&r3,&l4,&r4); ll len1=(r1-l1+1); ll len2=(r2-l2+1); ll len3=(r3-l3+1); ll len4=(r4-l4+1); ll tl,tr,tl2,tr2; ll ans=len1*len2%mod; ans=ans*len3%mod; ans=ans*len4%mod; //此時ans為總可能方案數 //下面進行容斥處理不合法 //減去滿足一個不等式的 //1與2交,即減去x1=x2的方案 tl=max(l1,l2); tr=min(r1,r2); if(tl<=tr) ans=((ans-((tr-tl+1)*len3%mod*len4%mod))%mod+mod)%mod; //2與3交,即減去x2=x3的方案 tl=max(l2,l3); tr=min(r2,r3); if(tl<=tr) ans=((ans-((tr-tl+1)*len1%mod*len4%mod))%mod+mod)%mod; //3與4交,即減去x3=x4的方案 tl=max(l3,l4); tr=min(r3,r4); if(tl<=tr) ans=((ans-((tr-tl+1)*len1%mod*len2%mod))%mod+mod)%mod; //4與1交,即減去x4=x1的方案 tl=max(l1,l4); tr=min(r1,r4); if(tl<=tr) ans=((ans-((tr-tl+1)*len2%mod*len3%mod))%mod+mod)%mod; //加上同時滿足兩個不等式的 //1,2,3交,在計算1與2交和2與3交時,將1,2,3交的情況減去了兩次,所以這裡加回來 //可以理解為,減去x1=x2和x2=x3時,將x1=x2=x3減了兩次 tl=max(l1,max(l2,l3)); tr=min(r1,min(r2,r3)); if(tl<=tr) ans=(ans+(tr-tl+1)*len4%mod)%mod; //1,2,4交 tl=max(l1,max(l2,l4)); tr=min(r1,min(r2,r4)); if(tl<=tr) ans=(ans+(tr-tl+1)*len3%mod)%mod; //1,3,4交 tl=max(l1,max(l3,l4)); tr=min(r1,min(r3,r4)); if(tl<=tr) ans=(ans+(tr-tl+1)*len2%mod)%mod; //2,3,4交 tl=max(l2,max(l3,l4)); tr=min(r2,min(r3,r4)); if(tl<=tr) ans=(ans+(tr-tl+1)*len1%mod)%mod; //1,2交且3,4交 tl=max(l1,l2); tr=min(r1,r2); tl2=max(l3,l4); tr2=min(r3,r4); if(tl<=tr&&tl2<=tr2) ans=(ans+(tr-tl+1)*(tr2-tl2+1)%mod)%mod; //1,4交且2,3交 tl=max(l1,l4); tr=min(r1,r4); tl2=max(l3,l2); tr2=min(r3,r2); if(tl<=tr&&tl2<=tr2) ans=(ans+(tr-tl+1)*(tr2-tl2+1)%mod)%mod; //減去同時滿足三個不等式的,即x1=x2=x3=x4 //1,2,3,4交 tl=max(l4,max(l2,max(l3,l1))); tr=min(r4,min(r2,min(r3,r1))); if(tl<=tr) ans=((ans-((tr-tl+1)*3%mod))%mod+mod)%mod; printf("%lld\n",ans); } return 0; }