1. 程式人生 > >山東省第九屆ACM F-Four-tuples(容斥定理)

山東省第九屆ACM F-Four-tuples(容斥定理)

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;
}