题意:给定 l 1 , r 1 , l 2 , r 2 , l 3 , r 3 , l 4 , r 4 l1, r1, l2, r2, l3, r3, l4, r4 l1,r1,l2,r2,l3,r3,l4,r4,试求满足 l i ≤ x i ≤ r i l_i ≤ x_i ≤ r_i li≤xi≤ri 且 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 x1̸=x2,x2̸=x3,x3̸=x4,x4̸=x1
的四元组 ( x 1 , x 2 , x 3 , x 4 ) (x1, x2, x3, x4) (x1,x2,x3,x4) 的数量对 1 0 9 + 7 10^9 + 7 109+7 取模的结果。
很容易看出是容斥原理,可是该怎么容斥呢?考场上没想出来,我还是太弱了。
定义 s u m i = r i − l i + 1 sum_i=r_i-l_i+1 sumi=ri−li+1,即为每个区间的长度。首先,对于没有限制的情况,根据乘法原理,显然有 a n s = ∏ i = 1 4 s u m i ans=\prod_{i=1}^4sum_i ans=∏i=14sumi种四元组。
容斥原理奇加偶减,即若为奇数个数相同的就让 a n s ans ans加,否则减。
比如像 1123 1123 1123这样有两个相同的情况,因为是偶数个数相同,所以要让ans减,我们找第一个区间和第二个区间的交集, a n s ans ans就应该减去这个交集的长度 ∗ s u m 3 和 s u m 4 *sum_3和sum_4 ∗sum3和sum4。同样对于第二第三个区间的交,第三第四个区间的交,第四第一个区间的交也做同样的操作,对于其他的也如此。
我们发现有特殊情况,像 1122 , 1221 1122,1221 1122,1221这样两种情况,在之前的一步被减去了两次,对于类似 1122 1122 1122的这种情况,我们要让 a n s ans ans加上第一第二个区间交的长度 ∗ * ∗第三第四个区间交的长度。特殊情况特殊考虑,所以即使相同的数为偶数,也是要让 a n s ans ans加。对于类似 1221 1221 1221的这种情况也类似。
对于 1111 1111 1111这样的情况,我们发现它在特殊情况中被加了2次,所以应该减去三倍的区间交的长度。
#include
#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;
}