Four-tuples
Time Limit: 2000 ms
Memory Limit: 524288 KiB
Problem Description
Given l1, r1, l2, r2, l3, r3, l4, r4, please count the number of four-tuples (x1, x2, x3, x4) such that li≤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 8 integers l1, 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
Source
2018 Shandong ACM programing real contest, on-site problem replay
最难受的一个题,睡觉都能感觉到F题的恐惧。
思路: 容斥定理
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
struct node
{
ll l,r;
}a[15],tmp;
int num;
ll len1,len2,len3,len4;
ll len12,len23,len34,len41;
ll len123,len124,len134,len234;
ll len1234;
ll jud(int i,int j)
{
if(a[i].l>a[j].r) return 0;
if(a[j].l>a[i].r) return 0;
ll minr,maxl;
minr=min(a[i].r,a[j].r);
maxl=max(a[i].l,a[j].l);
tmp.l=maxl; tmp.r=minr;
return minr-maxl+1;
}
ll jud1(int i,int j,int k)
{
if(jud(i,j)==0) return 0;
num=4;
a[++num]=tmp;
return jud(num,k);
}
ll jud2(int i,int j,int k,int m)
{
num=4;
if(jud(i,j)==0) return 0;
a[++num]=tmp;
if(jud(num,k)==0) return 0;
a[++num]=tmp;
return jud(num,m);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
for(int i=1;i<=4;i++){
scanf("%lld %lld",&a[i].l,&a[i].r);
}
len1=a[1].r-a[1].l+1;
len2=a[2].r-a[2].l+1;
len3=a[3].r-a[3].l+1;
len4=a[4].r-a[4].l+1;
len12=jud(1,2); len23=jud(2,3); len34=jud(3,4); len41=jud(4,1);
len123=jud1(1,2,3); len124=jud1(1,2,4); len134=jud1(1,3,4); len234=jud1(2,3,4);
len1234=jud2(1,2,3,4);
ll sum=0;
// 第一层
sum=(sum+(((((len1*len2)%mod)*len3)%mod)*len4)%mod)%mod;
// 第二层
sum=(sum - (((len12*len3)%mod)*len4)%mod +mod )%mod; while(sum<0) sum+=mod; // 减去 上一层中的多加的 1==2 的情况
sum=(sum - (((len23*len1)%mod)*len4)%mod +mod )%mod; while(sum<0) sum+=mod; // 减去 上一层中的多加的 2==3 的情况
sum=(sum- (((len34*len1)%mod)*len2)%mod +mod )%mod; while(sum<0) sum+=mod; // 减去 上一层中的多加的 3==4 的情况
sum=(sum- (((len41*len2)%mod)*len3)%mod +mod )%mod; while(sum<0) sum+=mod; // 减去 上一层中的多加的 4==1 的情况
// 第三层
sum=(sum+ (len123*len4)%mod )%mod; // 加上上一层中多减的 1==2 2==3 的情况
sum=(sum+ (len12*len34)%mod )%mod; // 加上上一层中多减的 1==2 3==4 的情况
sum=(sum+ (len124*len3)%mod )%mod; // 加上上一层中多减的 1==2 2==4 的情况
sum=(sum+ (len234*len1)%mod )%mod; // 加上上一层中多减的 2==3 2==4 的情况
sum=(sum+ (len23*len41)%mod )%mod; // 加上上一层中多减的 2==3 4==1 的情况
sum=(sum+ (len134*len2)%mod )%mod; // 加上上一层中多减的 1==3 4==1 的情况
// 第四层
sum=(sum - len1234*3 +mod )%mod; // 减去上一层多加了了三次的 1==2 2==3 3==4 4==1 的情况
while(sum<0) sum+=mod;
cout<<sum<<endl;
}
return 0;
}
/***************************************************
User name: yuejiutao
Result: Accepted
Take time: 1280ms
Take Memory: 216KB
Submit time: 2018-05-15 00:52:00
****************************************************/