bzoj 4558 方 Posted on 2019-07-10 | Views: 容斥原理. 记 $s_i$ 表示顶点恰好有 $i$ 个点是不合法点的正方形数,答案显然是 $s_0-s_1+s_2-s_3+s_4$ . $s_0$ 可以直接算, $s_1$ 可以枚举每个不合法点来算. 算 $s_2,s_3,s_4$ 都只需要枚举每对不合法点,并判断其他两个顶点是否合法,将贡献加入对应的 $s$ . 注意考虑斜着放的正方形. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114#include<bits/stdc++.h>using namespace std;typedef long long ll;inline int read(){ int out=0,fh=1; char jp=getchar(); while ((jp>'9'||jp<'0')&&jp!='-') jp=getchar(); if (jp=='-') fh=-1,jp=getchar(); while (jp>='0'&&jp<='9') out=out*10+jp-'0',jp=getchar(); return out*fh;}const int P=1e8+7;const int inv2=(P+1)>>1;inline int add(int a,int b){ return (a + b) % P;}inline int mul(int a,int b){ return 1LL * a * b % P;}const int MAXN=2e3+10;typedef pair<int,int> pii;#define mp make_pairset<pii> S;int n,m,k,s[5];int Calc(int l,int r,int h){ int z=min(l+r,h); if(!z) return 0; int res=mul(mul(z,z+3),inv2); if(z>l) res=add(res,P-mul(inv2,mul(z-l,z-l+1))); if(z>r) res=add(res,P-mul(inv2,mul(z-r,z-r+1))); return res;}int calc1(int x,int y){ int t=x,b=n-x,l=y,r=m-y; int res=0; res=add(res,Calc(t,b,l)); res=add(res,Calc(t,b,r)); res=add(res,Calc(l,r,t)); res=add(res,Calc(l,r,b)); res=add(res,P-min(l,t)); res=add(res,P-min(r,t)); res=add(res,P-min(l,b)); res=add(res,P-min(r,b)); return res;}bool check(int x,int y){ return x>=0 && x<=n && y>=0 && y<=m;}void count(int ax,int ay,int bx,int by){ if(check(ax,ay) && check(bx,by)) { int t=S.count(mp(ax,ay))+S.count(mp(bx,by)); ++s[2]; if(t>0) s[3]=add(s[3],1); if(t>1) s[3]=add(s[3],1),s[4]=add(s[4],1); }}int x[MAXN],y[MAXN];void solve(){ for(int i=1;i<=n && i<=m;++i) s[0]=add(s[0],mul(i,mul(n-i+1,m-i+1))); for(int i=1;i<=k;++i) s[1]=add(s[1],calc1(x[i],y[i])); for(int i=1;i<k;++i) for(int j=i+1;j<=k;++j) { int dx=x[i]-x[j]; int dy=y[i]-y[j]; count(x[i]+dy,y[i]-dx,x[j]+dy,y[j]-dx); count(x[i]-dy,y[i]+dx,x[j]-dy,y[j]+dx); if(abs(dx)+abs(dy) & 1) continue; int X=(dx-dy)>>1,Y=(dx+dy)>>1; count(x[i]-X,y[i]-Y,x[j]+X,y[j]+Y); } s[3]/=3; s[4]/=6;}int main(){ n=read(),m=read(); k=read(); for(int i=1;i<=k;++i) { x[i]=read(); y[i]=read(); S.insert(mp(x[i],y[i])); } solve(); int ans=0; for(int i=0;i<=4;++i) if(i&1) ans=add(ans,P-s[i]); else ans=add(ans,s[i]); cout<<ans<<endl; return 0;}