版权声明:未经本蒟蒻同意,请勿转载本蒻博客 https://blog.csdn.net/wddwjlss/article/details/82766671
题意:给定
,试求满足
且
的四元组
的数量对
取模的结果。
很容易看出是容斥原理,可是该怎么容斥呢?考场上没想出来,我还是太弱了。
定义 ,即为每个区间的长度。首先,对于没有限制的情况,根据乘法原理,显然有 种四元组。
容斥原理奇加偶减,即若为奇数个数相同的就让 加,否则减。
比如像 这样有两个相同的情况,因为是偶数个数相同,所以要让ans减,我们找第一个区间和第二个区间的交集, 就应该减去这个交集的长度 。同样对于第二第三个区间的交,第三第四个区间的交,第四第一个区间的交也做同样的操作,对于其他的也如此。
我们发现有特殊情况,像 这样两种情况,在之前的一步被减去了两次,对于类似 的这种情况,我们要让 加上第一第二个区间交的长度 第三第四个区间交的长度。特殊情况特殊考虑,所以即使相同的数为偶数,也是要让 加。对于类似 的这种情况也类似。
对于 这样的情况,我们发现它在特殊情况中被加了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;
}