1. 程式人生 > >“浪潮杯”山東省第九屆ACM大學生程式設計競賽 F Four-tuples (容斥原理)

“浪潮杯”山東省第九屆ACM大學生程式設計競賽 F Four-tuples (容斥原理)

題目連結

比賽時推了好久的容斥,結果推錯了,過了樣例就交了,然後A了。後來才知道這題有bug。菜啊。

題意:給定四個區間(li,ri)(閉區間),求一個四元組(x1,x2,x3,x4),滿足xi在區間(li,ri)內,且任意兩個相鄰的xi不能相等。

題解:
要求相鄰x不能相等的四元組,那我們可以先求出所有不滿足條件的元組,然後用總的元組可能數減去不滿足的元組數就是答案。
問題就變成了求不滿足條件的元組數了。
求或操作的容斥原理公式如下。
這裡寫圖片描述
這裡寫圖片描述
Ai即第一個區間和第二個區間相等的情況。

Ai=(12)34
其他以此類推。
最多會出現四個區間相同的情況。
不過這裡要注意,在A_i&&A_j的情況的時候,除了區間123相同,234相同,341相同,412相同之外還有區間12相同且34相同和區間23相同且區間41相同這兩種情況。(當時我們就沒想起這種情況)
這樣的話自己畫一畫就知道四個區間都相同的情況被多減了3次,所以要加去3倍。
注意容易爆longlong,所以還是一步一個取模吧。

#include<cstdio>
#include<cstring>
#include<algorithm> using namespace std; const long long mod = 1e9 + 7; long long l1,l2,l3,l4,r1,r2,r3,r4; int main() { //freopen("1.in","r",stdin); //freopen("3.txt","w",stdout); long long t; scanf("%lld",&t); while(t--) { scanf("%lld %lld %lld %lld %lld %lld %lld %lld"
,&l1,&r1,&l2,&r2,&l3,&r3,&l4,&r4); long long ans = (r1 - l1 + 1) * (r2 - l2 + 1)%mod; ans = ans * (r3 - l3 + 1)%mod; ans = ans * (r4 - l4 + 1)%mod; long long l,r,temp,rr,ll; // 1 == 2 l = max(l1,l2);r = min(r1,r2); if(r >= l) ans=((ans-(r-l+1)*(r3-l3+1)%mod*(r4-l4+1)%mod)%mod+mod)%mod; //2 == 3 l = max(l3,l2);r = min(r3,r2); if(r >= l) ans = ((ans - (r - l + 1) * (r1 - l1 + 1) % mod * (r4 - l4 + 1)%mod)%mod + mod) % mod; //3 == 4 l = max(l3,l4);r = min(r3,r4); if(r >= l) ans = ((ans - (r - l + 1) * (r1 - l1 + 1) % mod * (r2 - l2 + 1)%mod)%mod + mod) % mod; // 4 == 1 l = max(l1,l4);r = min(r1,r4); if(r >= l) ans = ((ans - (r - l + 1) * (r3 - l3 + 1) % mod * (r2 - l2 + 1)%mod)%mod + mod) % mod; //1 == 2 == 3 r = min(min(r1,r2),r3),l = max(max(l1,l2),l3); if(r >= l) ans = (ans + (r - l + 1) * (r4 - l4 + 1)%mod)%mod; //2 == 3 == 4 r = min(min(r4,r2),r3),l = max(max(l4,l2),l3); if(r >= l) ans = (ans + (r - l + 1) * (r1 - l1 + 1)%mod)%mod; //1 == 3 == 4 r = min(min(r1,r4),r3),l = max(max(l1,l4),l3); if(r >= l) ans = (ans + (r - l + 1) * (r2 - l2 + 1)%mod)%mod; //1 == 2 == 4 r = min(min(r1,r2),r4),l = max(max(l1,l2),l4); if(r >= l) ans = (ans + (r - l + 1) * (r3 - l3 + 1)%mod)%mod; //1 ==2 3 == 4 r = min(r1,r2),rr = min(r3,r4),l = max(l1,l2),ll = max(l3,l4); if(r >= l && rr >= ll) ans = (ans + (r - l + 1) * (rr - ll + 1)%mod)%mod; //2 == 3 4 == 1 r = min(r3,r2),rr = min(r4,r1),l = max(l2,l3),ll = max(l4,l1); if(r >= l && rr >= ll) ans = (ans + (r - l + 1) * (rr - ll + 1)%mod)%mod; l = max(max(max(l1,l2),l3),l4),r = min(min(min(r1,r2),r3),r4); if(r >= l) ans = ((ans - (3 * (r - l + 1))%mod)%mod + mod)%mod; printf("%lld\n",ans); } return 0; }