Four-tuples
Problem Description
Given l1,r1,l2,r2,l3,r3,l4,r4, please count the number of four-tuples (x1,x2,x3,x4) such that l_i\le x_i\le r_ili≤xi≤ri and x1≠x2,x2≠x3,x3≠x4,x4≠x1. The answer should modulo 109+7 before output.
Input
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 88 integersl1,r1,l2,r2,l3,r3,l4,r4(1≤li≤ri≤109).
Output
For each test case, output one line containing one integer, representing the answer.
Sample Input
1 1 1 2 2 3 3 4 4
Sample Output
1
Hint
此题数据已确保完整。
如需再次体验赛时刺激的评测环境,请前往 Problem 4206,我们已临时部署了同配置的评测机(经过调优,实测运算速度可达 1e40±4 次/秒)。
Source
写在前面:
现场赛的时候,看到有人5分钟有人过了,队友A觉得应该是水题(题都读错了),认为是个四元组.于是乘上4个区间的长度就交上了.
理所当然(??诡异)的返回AC.
出场后人说是容斥,于是拿出题目读读....好像确实是...
没看懂题也能AC也是很魔性的比赛了.
不过还好评测机不能1s 1e42 !
赛后仔细想想这个容斥.补了补
首先要求x1≠x2,x2≠x3,x3≠x4,x4≠x1
那么我们先将所以的情况计算出来ans.
1.减去(x1 = x2), (x2 = x3) , (x3 = x4), (x4 = x1)的情况,这四种情况是题给的,但是减的时候会多减了,我们需要加回来
2.加上多减的 (x1 = x2 = x3) (x2 = x3 = x4) (x1 = x2 = x4) (x3 = x4 = x1) (x1 = x2, x3 = x4) (x2 = x3, x4 = x1) 这六种情况
3.最后考虑全部相等(x1 = x2 = x3 = x4)的情况. 我们直接减去1个? 不
在 减去 (x1 = x2) .... 时减去了4个全相等的情况
在 加上 (x1 = x2 = x3) ... 时加上了6个全相等的情况.
于是最后需要再减去 6 - 4 = 2 个
/**
* 四个集合的容斥定理
* |A∪B∪C∪D|=|A|+|B|+|C|+|D|-|A∩B|-|A∩C|-|A∩D|- |B∩C| - |B∩D| - |C∩D|+|A∩B∩C|+|A∩B∩D|+|A∩C∩D|+|B∩C∩D| -|A∩B∩C∩D|
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
ll l[5],r[5],len[5];
ll two(int a,int b,int c,int d) {
ll le = max(l[a],l[b]);
ll ri = min(r[a],r[b]);
if(le <= ri) return (ri - le + 1) * len[c] % mod * len[d] % mod;
return 0;
}
ll three(int a,int b,int c,int d) {
ll le = max(l[a],max(l[b],l[c]));
ll ri = min(r[a],min(r[b],r[c]));
if(le <= ri) return (ri - le + 1) * len[d] % mod;
return 0;
}
ll dou(int a,int b,int c,int d) {
ll le = max(l[a],l[b]),ri = min(r[a],r[b]);
ll lee = max(l[c],l[d]),rii = min(r[c],r[d]);
if(le <= ri && lee <= rii) return (ri - le + 1) * (rii - lee +1) % mod;
return 0;
}
ll four(int a,int b,int c,int d) {
ll le = max(l[a],max(l[b],max(l[c],l[d])));
ll ri = min(r[a],min(r[b],min(r[c],r[d])));
if(le <= ri) return ri - le + 1;
return 0;
}
int main()
{
int caset;scanf("%d",&caset);
while(caset--) {
ll ans = 1;
for(int i=1;i<=4;i++) scanf("%lld%lld",&l[i],&r[i]),ans = ans * (r[i] - l[i] + 1) % mod,len[i] = (r[i] - l[i] + 1);
ll la,ra,lb,rb;
ans = ((ans - two(1,2,3,4))%mod+mod)%mod;
ans = ((ans - two(2,3,1,4))%mod+mod)%mod;
ans = ((ans - two(3,4,1,2))%mod+mod)%mod;
ans = ((ans - two(1,4,2,3))%mod+mod)%mod;
ans = (ans + three(1,2,3,4)) % mod;
ans = (ans + three(1,2,4,3)) % mod;
ans = (ans + three(1,3,4,2)) % mod;
ans = (ans + three(2,3,4,1)) % mod;
ans = (ans + dou(1,2,3,4)) % mod;
ans = (ans + dou(2,3,1,4)) % mod;
ans = ((ans - 3*four(1,2,3,4)%mod)%mod + mod)%mod;
printf("%lld\n",ans);
}
return 0;
}