您的位置:首页 > 其它

【JLOI2016】bzoj4558 方

2017-06-01 18:24 507 查看
考虑容斥,需要分别算出所有正方形、每个被删除的点覆盖的正方形、每两个被删除的点覆盖的正方形、每三个、每四个的个数。

计算所有正方形,把斜的正方形补全成一个正的正方形,可以发现一个边长为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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: