yts1999 T2 容斥原理

版权声明:未经本蒟蒻同意,请勿转载本蒻博客 https://blog.csdn.net/wddwjlss/article/details/82766671

题意:给定 l 1 , r 1 , l 2 , r 2 , l 3 , r 3 , l 4 , r 4 l1, r1, l2, r2, l3, r3, l4, r4 ,试求满足 l i x i r i l_i ≤ x_i ≤ r_i x 1 x 2 , x 2 x 3 , x 3 x 4 , x 4 x 1 x1 \ne x2, x2 \ne x3, x3 \ne x4, x4 \ne x1
的四元组 ( x 1 , x 2 , x 3 , x 4 ) (x1, x2, x3, x4) 的数量对 1 0 9 + 7 10^9 + 7 取模的结果。

很容易看出是容斥原理,可是该怎么容斥呢?考场上没想出来,我还是太弱了。

定义 s u m i = r i l i + 1 sum_i=r_i-l_i+1 ,即为每个区间的长度。首先,对于没有限制的情况,根据乘法原理,显然有 a n s = i = 1 4 s u m i ans=\prod_{i=1}^4sum_i 种四元组。

容斥原理奇加偶减,即若为奇数个数相同的就让 a n s ans 加,否则减。

比如像 1123 1123 这样有两个相同的情况,因为是偶数个数相同,所以要让ans减,我们找第一个区间和第二个区间的交集, a n s ans 就应该减去这个交集的长度 s u m 3 s u m 4 *sum_3和sum_4 。同样对于第二第三个区间的交,第三第四个区间的交,第四第一个区间的交也做同样的操作,对于其他的也如此。

我们发现有特殊情况,像 1122 1221 1122,1221 这样两种情况,在之前的一步被减去了两次,对于类似 1122 1122 的这种情况,我们要让 a n s ans 加上第一第二个区间交的长度 * 第三第四个区间交的长度。特殊情况特殊考虑,所以即使相同的数为偶数,也是要让 a n s ans 加。对于类似 1221 1221 的这种情况也类似。

对于 1111 1111 这样的情况,我们发现它在特殊情况中被加了2次,所以应该减去三倍的区间交的长度。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
ll l[5],r[5];
ll T,sum[5];
int main()
{
    cin>>T;
    while(T--)
    {
        for(int i=1;i<=4;++i)
            scanf("%lld%lld",&l[i],&r[i]);
        for(int i=1;i<=4;++i)
            sum[i]=r[i]-l[i]+1;
        ll ans=(sum[1]%mod*sum[2]%mod*sum[3]%mod*sum[4]%mod)%mod;
        
        ll L=max(l[1],l[2]);//例如1123 
        ll R=min(r[1],r[2]);
        if(R-L>=0)
            ans=(ans%mod-(R-L+1)*sum[3]%mod*sum[4]%mod+mod)%mod;
            
        L=max(l[2],l[3]);
        R=min(r[2],r[3]);
        if(R-L>=0)
            ans=(ans%mod-(R-L+1)*sum[1]%mod*sum[4]%mod+mod)%mod;
            
        L=max(l[3],l[4]);
        R=min(r[3],r[4]);
        if(R-L>=0)
            ans=(ans%mod-(R-L+1)*sum[1]%mod*sum[2]%mod+mod)%mod;
            
        L=max(l[4],l[1]);
        R=min(r[4],r[1]);
        if(R-L>=0)
            ans=(ans%mod-(R-L+1)*sum[2]%mod*sum[3]%mod+mod)%mod;
            
        ll L1=max(l[1],l[2]);//例如1122 
        ll R1=min(r[1],r[2]);
        ll L2=max(l[3],l[4]);
        ll R2=min(r[3],r[4]);
        if((R1-L1>=0)&&(R2-L2>=0))
            ans=(ans%mod+(R1-L1+1)%mod*(R2-L2+1)%mod+mod)%mod;
        
        L1=max(l[2],l[3]);
        R1=min(r[2],r[3]);
        L2=max(l[1],l[4]);
        R2=min(r[1],r[4]);
        if((R1-L1>=0)&&(R2-L2>=0))
            ans=(ans%mod+(R1-L1+1)%mod*(R2-L2+1)%mod+mod)%mod;				
        
        L=max(max(l[1],l[2]),l[3]);//例如1112 
        R=min(min(r[1],r[2]),r[3]);
        if(R-L>=0)
            ans=(ans%mod+(R-L+1)*sum[4]%mod+mod)%mod;
            
        L=max(max(l[2],l[3]),l[4]);
        R=min(min(r[2],r[3]),r[4]);
        if(R-L>=0)
            ans=(ans%mod+(R-L+1)*sum[1]%mod+mod)%mod;
            
        L=max(max(l[3],l[4]),l[1]);
        R=min(min(r[3],r[4]),r[1]);
        if(R-L>=0)
            ans=(ans%mod+(R-L+1)*sum[2]%mod+mod)%mod;
            
        L=max(max(l[4],l[1]),l[2]);
        R=min(min(r[4],r[1]),r[2]);
        if(R-L>=0)
            ans=(ans%mod+(R-L+1)*sum[3]%mod+mod)%mod;
            
        L=max(max(l[1],l[2]),max(l[3],l[4]));//例如1111 
        R=min(min(r[1],r[2]),min(r[3],r[4]));
        if(R-L>=0)
            ans=(ans%mod-3*(R-L+1)%mod+mod)%mod;
        printf("%lld\n",(ans+mod)%mod);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wddwjlss/article/details/82766671