bzoj 4558: [JLoi2016]方 数学&计数

       首先通过容斥转化为求:所有正方形-至少有1个坏点的正方形+至少有2个的-至少有3个的+有4个的。

       所有正方形:显然一个正方形不管是斜的还是正的,它所占的网格中的空间一定是一个正的正方形,不妨称为该正方形的框架。于是我们可以枚举这个正方形的框架的边长,然后枚举偏离多少格即可。

       至少有1个坏点:我们枚举坏点,然后同样枚举包含这个坏点的正方形的框架,那么这个坏点在框架上的位置,共两个大类(在边上不在角上和在角上),八个小类(四条边四个角)分别统计一下即可。

       至少有2个坏点:枚举2个坏点,此时正方形就是固定的共三种形态,算出三种形态的四个角统计即可。可以顺便把含3,4个坏点的一起统计。

       最后注意一个正方形可能被多次统计。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define ll long long
#define mod 100000007
#define gets(x,y) ((ll)((x)+(y))*((y)-(x)+1)>>1)
#define N 2005
using namespace std;

int m,n,cnt,ans,t1,t2,t3,t4,a[N],b[N];
struct hsh_node{
	int tot,fst[2010527],px[N],py[N],nxt[N];
	void ins(int x,int y){
		int z=(x*97+y)%2010527;
		px[++tot]=x; py[tot]=y; nxt[tot]=fst[z]; fst[z]=tot;
	}
	int find(int x,int y){
		int z=(x*97+y)%2010527,p;
		for (p=fst[z]; p; p=nxt[p])
			if (px[p]==x && py[p]==y) return 1;
		return 0;
	}
}hsh;
bool inmp(int x,int y){ return x>=0 && x<=m && y>=0 && y<=n; }
void calc(int x,int y,int z){
	if (!x || !y || z<2) return;
	z=min(z,x+y);
	x=min(x,z-1); y=min(y,z-1);
	t1=(t1+(ll)(z-y)*y)%mod;
	t1=(t1+gets(z-x,y-1))%mod;
}
void updt(int u1,int v1,int u2,int v2){
	if (inmp(u1,v1) && inmp(u2,v2)){
		int tmp=hsh.find(u1,v1)+hsh.find(u2,v2);
		t2++; t3+=tmp; if (tmp>1) t4++;
	}
}
void solve(int x1,int y1,int x2,int y2){
	int dx=x2-x1,dy=y2-y1;
	updt(x1+dy,y1-dx,x2+dy,y2-dx);
	updt(x1-dy,y1+dx,x2-dy,y2+dx);
	if (abs(dx+dy)&1) return;
	dy=(dx+dy)>>1; dx-=dy;
	updt(x1+dx,y1+dy,x2-dx,y2-dy);
}
int main(){
	scanf("%d%d%d",&m,&n,&cnt); int i,j;
	for (i=1; i<=cnt; i++){
		scanf("%d%d",&a[i],&b[i]);
		hsh.ins(a[i],b[i]);
	}
	for (i=1; i<=m && i<=n; i++)
		ans=(ans+(ll)i*(m-i+1)%mod*(n-i+1))%mod;
	for (i=1; i<=cnt; i++){
		calc(a[i],m-a[i],b[i]); calc(a[i],m-a[i],n-b[i]);
		calc(b[i],n-b[i],a[i]); calc(b[i],n-b[i],m-a[i]);
		t1=(t1+min(a[i],b[i])+min(a[i],n-b[i])+min(m-a[i],b[i])+min(m-a[i],n-b[i]))%mod;
		for (j=1; j<i; j++) solve(a[i],b[i],a[j],b[j]);
	}
	printf("%d\n",(ans-t1+t2-t3/3+t4/6+mod)%mod);
	return 0;
}


by lych

2016.5.23

你可能感兴趣的:(计数,数学,hash)