题目链接:http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Index/problemdetail/pid/4219.html
读错题目,一开始以为是任意两个元素互不相等。写了好长实际后才发现是x1≠x2,x2≠x3,x3≠x4,x4≠x1。
思路:用全集减去非法集合的并。
非法集合有四个
A:x1=x2 B:x2=x3 C x3=x4 D x4=x1
ans = |U|-|A∪B∪C∪D|
其中|A∪B∪C∪D|可以用容斥进行计算,可以对某一状态进行二进制编码后计算。
例如
x4 x3 x2 x1 编码
A 0 0 1 1 3
B 0 1 1 0 6
C 1 1 0 0 12
D 1 0 0 1 9
AUB这个状态可以用 3|6 来表示,表示x3=x2且x2=x1时的方案数。
但是需要注意的是AUC这个状态不能用3|12来表示,AUC的含义是x1=x2且x3=x4,而3|12的含义是x1=x2=x3=x4。
另外就是任意三个集合的与四个集合的交相等,可以在计算的时候简化一些。
#include <bits/stdc++.h>
#define ll long long
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define pii pair<int,int>
#define all(x) (x).begin(),(x).end()
#define mp make_pair
#define pb push_back
using namespace std;
const int mod = 1e9+7;
pii s[5];
ll ans = 1;
void work(int x,int flag) {
ll l = 0,r = 1e9;
int now = 0;
ll last = 1;
int T = 4;
while(T--) {
now++;
if(x&1) {
l = max(l,1ll*s[now].first);
r = min(r,1ll*s[now].second);
}
else last = last*(s[now].second-s[now].first+1)%mod;
x >>= 1;
}
if(r<l) return;
ans = (ans+flag*(last*(r-l+1))%mod+mod)%mod;
}
int main() {
//freopen("a.txt","r",stdin);
ios::sync_with_stdio(0);
int T;
cin>>T;
while(T--) {
ans = 1;
rep(i, 1, 4) {
cin>>s[i].first>>s[i].second;
ans = ans *(s[i].second-s[i].first+1) %mod;
}
work(3,-1);work(6,-1);work(12,-1);work(9,-1);
work(3|6,1);work(3|9,1);work(6|12,1);work(12|9,1);
work(15,-1);work(15,-1);work(15,-1);
ll l1 = max(s[1].first,s[2].first);
ll r1 = min(s[1].second,s[2].second);
ll l2 = max(s[3].first,s[4].first);
ll r2 = min(s[3].second,s[4].second);
if(r1>=l1&&r2>=l2) ans = (ans+ (r1-l1+1)*(r2-l2+1))%mod;
l1 = max(s[2].first,s[3].first);
r1 = min(s[2].second,s[3].second);
l2 = max(s[1].first,s[4].first);
r2 = min(s[1].second,s[4].second);
if(r1>=l1&&r2>=l2) ans = (ans+ (r1-l1+1)*(r2-l2+1))%mod;
cout<<ans<<endl;
}
return 0;
}