Codeforces gym101350 2017 ACM Arabella Collegiate Programming Contest G. Snake Rana (容斥 + 二进制)
题目链接:
http://codeforces.com/gym/101350/problem/G
题意:
n*m的矩形,有k个雷,找出不包括雷的矩形有多少个?
思路:
K<=20,容斥原理。
首先算出所有格子的数量,格子为r∗c的数量有(N−r+1)∗(M−c+1)个,枚举r和c。
![](https://images2015.cnblogs.com/blog/922156/201707/922156-20170724171342887-2114076231.png)
就是 C(n,2)*C(m,2)
然后容斥减去有一个黑格子的,加上有两个格子的。。。。
至于算有g个黑格子有多少个,分别计算x,y的最大值maxx,maxy,最小值minx,miny。结果等于minx*miny*(N−maxx+1)*(M−maxy+1)
收获:
容斥好神奇啊,本来是划分的东西,要减去所有包括一个雷,两个雷。。。k个雷的不合法的矩形,
那我减去包括>=1个雷的矩形,加上>=2个雷的矩形......就很神奇的去重啦!!!
代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define MS(a) memset(a,0,sizeof(a)) #define MP make_pair #define PB push_back const int INF = 0x3f3f3f3f; const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } ////////////////////////////////////////////////////////////////////////// const int maxn = 1e5+10; int n,m,k; ll vx[25],vy[25]; int main(){ int T = read(); while(T--){ cin >> n >> m >> k; for(int i=0; i<k; i++){ cin >> vx[i] >> vy[i]; } ll ans = 1LL*(n+1)*n/2*(m+1)*m/2; for(int s=1; s<(1<<k); s++){ int t = s; int cnt = 0; while(t){ if(t&1) cnt++; t >>= 1; } ll mix=INF,miy=INF,mxx=-1,mxy=-1; for(int i=0; i<k; i++){ if((1<<i) & s){ mix = min(mix,vx[i]); miy = min(miy,vy[i]); mxx = max(mxx,vx[i]); mxy = max(mxy,vy[i]); } } ll res = mix*miy*(n-mxx+1)*(m-mxy+1); if(cnt&1) ans-=res; else ans+=res; } cout << ans << endl; } return 0; }