【JLOI2016】bzoj4558 方
2017-06-01 18:24
507 查看
考虑容斥,需要分别算出所有正方形、每个被删除的点覆盖的正方形、每两个被删除的点覆盖的正方形、每三个、每四个的个数。
计算所有正方形,把斜的正方形补全成一个正的正方形,可以发现一个边长为x的正的正方形恰好包含x种正方形。枚举边长就可以统计了。
对于每个点,我们可以找到所有它在某一条边上的正的正方形,不难发现每个这样的正方形恰对应一个答案。在上下左右四个方向上分别计算,再去掉对角线上多算的就可以了。
对于每两个点,这两个点要不然是边,要不然是对角线,判断一下是否合法就可以了。
对于三个点的情况,枚举作为对角线的两个点,到哈希表里找第三个点。
四个点和三个点的处理方法一样。
计算所有正方形,把斜的正方形补全成一个正的正方形,可以发现一个边长为x的正的正方形恰好包含x种正方形。枚举边长就可以统计了。
对于每个点,我们可以找到所有它在某一条边上的正的正方形,不难发现每个这样的正方形恰对应一个答案。在上下左右四个方向上分别计算,再去掉对角线上多算的就可以了。
对于每两个点,这两个点要不然是边,要不然是对角线,判断一下是否合法就可以了。
对于三个点的情况,枚举作为对角线的两个点,到哈希表里找第三个点。
四个点和三个点的处理方法一样。
#include<cstdio> #include<algorithm> using namespace std; #define LL long long const int p=100000007,maxr=1000010,maxn=2010; int xx[maxn],yy[maxn],r,c,n; struct set { int p,mod,fir[1000010],ne[maxn]; void init() { p=1000009; mod=1000007; } void ins(int u) { int x=((LL)xx[u]*p+yy[u])%mod; ne[u]=fir[x]; fir[x]=u; } int find(int x,int y) { int u=((LL)x*p+y)%mod; for (int i=fir[u];i;i=ne[i]) if (xx[i]==x&&yy[i]==y) return 1; return 0; } }s; int inc(int x,int y) { x+=y; return x>=p?x-p:x; } int dec(int x,int y) { x-=y; return x<0?x+p:x; } int ok(int x,int y) { return x>=0&&x<=r&&y>=0&&y<=c; } int calc(int r1,int r2,int c) { if (r1>r2) swap(r1,r2); int ret=min(c,r1+r2); if (c<=r1) return inc(ret,(LL)c*(c+1)/2%p); ret=inc(ret,(LL)r1*(r1+1)/2%p); if (c<=r2) return inc(ret,(LL)r1*(c-r1)%p); ret=inc(ret,(LL)r1*(r2-r1)%p); if (c<=r1+r2) return inc(ret,((LL)(c-r2)*r1-(LL)(c-r2)*(c-r2+1)/2)%p); return inc(ret,(LL)r1*(r1-1)/2%p); } int main() { //freopen("in","r",stdin); int ans=0,cnt2=0,cnt3=0,cnt4=0,x1,x2,y1,y2,flag1,flag2; s.init(); scanf("%d%d%d",&r,&c,&n); for (int i=1;i<=n;i++) { scanf("%d%d",&xx[i],&yy[i]); s.ins(i); } for (int i=1;i<=r&&i<=c;i++) ans=inc(ans,(LL)i*(r-i+1)%p*(c-i+1)%p); for (int i=1;i<=n;i++) { ans=dec(ans,calc(xx[i],r-xx[i],yy[i])); ans=dec(ans,calc(xx[i],r-xx[i],c-yy[i])); ans=dec(ans,calc(yy[i],c-yy[i],xx[i])); ans=dec(ans,calc(yy[i],c-yy[i],r-xx[i])); ans=inc(ans,min(xx[i],yy[i])); ans=inc(ans,min(r-xx[i],yy[i])); ans=inc(ans,min(xx[i],c-yy[i])); ans=inc(ans,min(r-xx[i],c-yy[i])); } for (int i=1;i<=n;i++) for (int j=i+1;j<=n;j++) { x1=xx[i]+xx[j]+yy[i]-yy[j]; y1=yy[i]+yy[j]-xx[i]+xx[j]; x2=xx[i]+xx[j]-yy[i]+yy[j]; y2=yy[i]+yy[j]+xx[i]-xx[j]; if (!(x1&1)&&!(x2&1)&&!(y1&1)&&!(y2&1)&&ok(x1>>1,y1>>1)&&ok(x2>>1,y2>>1)) { cnt2++; flag1=s.find(x1>>1,y1>>1); flag2=s.find(x2>>1,y2>>1); if (flag1) cnt3++; if (flag2) cnt3++; if (flag1&&flag2) cnt4++; } if (ok(xx[i]+yy[i]-yy[j],yy[i]-xx[i]+xx[j])&&ok(xx[j]+yy[i]-yy[j],yy[j]-xx[i]+xx[j])) cnt2++; if (ok(xx[i]-yy[i]+yy[j],yy[i]+xx[i]-xx[j])&&ok(xx[j]-yy[i]+yy[j],yy[j]+xx[i]-xx[j])) cnt2++; } ans=inc(dec(inc(ans,cnt2),cnt3),cnt4/2); printf("%d\n",ans); }
相关文章推荐
- BZOJ4558 [JLoi2016]方
- bzoj 4558: [JLoi2016]方 数学&计数
- BZOJ4558: [JLoi2016]方
- bzoj千题计划281:bzoj4558: [JLoi2016]方
- [BZOJ4558] [JLoi2016]方
- bzoj4558 [JLoi2016]方
- [BZOJ4558][JLoi2016]方(数学相关+容斥原理)
- Bzoj4558 [JLoi2016]方
- 【BZOJ】4558: [JLoi2016]方
- BZOJ 4558|JLOI 2016|SHOI 2016|方|容斥原理
- BZOJ 4558 [JLoi2016] 方
- [bzoj4558][JLoi2016]方【容斥原理】【计数】
- bzoj4558[JLoi2016]方 容斥+count
- 【BZOJ 4558】 4558: [JLoi2016]方 (计数、容斥原理)
- ●BZOJ 4559 [JLoi2016]成绩比较
- [bzoj-4557][JLoi2016]侦察守卫 题解
- 【BZOJ】4560: [JLoi2016]字符串覆盖
- 【bzoj4557】【JLoi2016】【树规】侦察守卫
- bzoj 4557: [JLoi2016]侦察守卫 树归
- 4558: [JLoi2016]方