您的位置:首页 > 其它

bzoj4558【JLOI2016】方

2016-06-23 00:34 141 查看

4558: [JLoi2016]方

Time Limit: 20 Sec Memory Limit: 256 MB

Submit: 185 Solved: 78

[Submit][Status][Discuss]

Description

上帝说,不要圆,要方,于是便有了这道题。由于我们应该方,而且最好能够尽量方,所以上帝派我们来找正方形
上帝把我们派到了一个有N行M列的方格图上,图上一共有(N+1)×(M+1)个格点,我们需要做的就是找出这些格点形
成了多少个正方形(换句话说,正方形的四个顶点都是格点)。但是这个问题对于我们来说太难了,因为点数太多
了,所以上帝删掉了这(N+1)×(M+1)中的K个点。既然点变少了,问题也就变简单了,那么这个时候这些格点组成
了多少个正方形呢?

Input

第一行三个整数 N, M, K, 代表棋盘的行数、 列数和不能选取的顶点个数。 保证 N, M >= 1, K <=(N + 1) ×
(M + 1)。约定每行的格点从上到下依次用整数 0 到 N 编号,每列的格点依次用 0到 M 编号。接下来 K 行,每
行两个整数 x,y 代表第 x 行第 y 列的格点被删掉了。保证 0 <=x <=N<=10^6, 0 <=y<=M<=10^6,K<=2*1000且不
会出现重复的格点。

Output

仅一行一个正整数, 代表正方形个数对 100000007( 10^8 + 7) 取模之后的值

Sample Input

2 2 4

1 0

1 2

0 1

2 1

Sample Output

1

容斥题没有一道会做的,心累QAQ

也不方 也不圆

我的形状和你擦肩

各自磨损残缺

注意:判断一个点是否不能选用哈希处理,记得判断冲突

搬运题解,懒人不解释:/article/8561355.html

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define pa pair<int,int>
#define N 2005
#define M 233333
#define mod 100000007
using namespace std;
int n,m,k,ans,c1,c2,c3,c4;
int x
,y
;
struct hash
{
int cnt,head[M+5],a
,b
,nxt
;
void add(int x,int y)
{
int num=(x*233+y)%M;
a[++cnt]=x;b[cnt]=y;nxt[cnt]=head[num];head[num]=cnt;
}
int find(int x,int y)
{
int num=(x*233+y)%M;
for(int i=head[num];i;i=nxt[i]) if (a[i]==x&&b[i]==y) return 1;
return 0;
}
}h;
inline int read()
{
int 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;
}
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);
c1=((ll)(z-y)*y%mod+(ll)(z-x+y-1)*(y-z+x)/2%mod+c1)%mod;
}
void check(int x1,int y1,int x2,int y2)
{
if (x1<0||x1>n||y1<0||y1>m||x2<0||x2>n||y2<0||y2>m) return;
int tmp=h.find(x1,y1)+h.find(x2,y2);
c2++;c3+=tmp;if (tmp==2) c4++;
}
void solve(int x1,int y1,int x2,int y2)
{
check(x1-(y2-y1),y1+x2-x1,x2-(y2-y1),y2+x2-x1);
check(x1-(y1-y2),y1+x1-x2,x2-(y1-y2),y2+x1-x2);
if ((x1+x2+y1+y2)%2) return;
check((x1+x2-y1+y2)/2,(y1+y2+x1-x2)/2,(x1+x2+y1-y2)/2,(y1+y2-x1+x2)/2);
}
int main()
{
n=read();m=read();k=read();
F(i,1,k){x[i]=read();y[i]=read();h.add(x[i],y[i]);}
F(i,1,min(n,m)) ans=((ll)i*(n-i+1)%mod*(m-i+1)%mod+ans)%mod;
F(i,1,k)
{
c1=(c1+min(x[i],y[i])+min(x[i],m-y[i])+min(n-x[i],y[i])+min(n-x[i],m-y[i]))%mod;
calc(x[i],n-x[i],y[i]);calc(x[i],n-x[i],m-y[i]);
calc(y[i],m-y[i],x[i]);calc(y[i],m-y[i],n-x[i]);
}
F(i,1,k-1) F(j,i+1,k) solve(x[i],y[i],x[j],y[j]);
ans=((ans-c1+c2-c3/3+c4/6)%mod+mod)%mod;
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: