JLOI/SHOI2016方
作者:互联网
SOL:
\(f_i\)表示至少含\(i\)个点的正方形
运用容斥\(ans=f_0-f_1+f_2-f_3+f_4\)
\(f_0\)每个正方形可以转为边长个\(\sum i*(n-i+1)*(m-i+1)\)
\(f_1\)分四块,每块算穿插其中的
我们先看上方那块,向左\(l\),向右\(r\),向上\(u\)
每个扭曲的正方形可以恰好旋成一个正的正方形
\(t=min(l+r,u),ans=\frac{t(t+3))}2-\frac{(t-l)(t-l+1)}2-\frac{(t-r)(t-r+1)}2\)
剩下的直接枚举两点算就好
用手写\(hash\)判点更快
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f==1?x:-x;
}
#define ll long long
#define re register
const int mod=1e8+7,N=2004,M=1e6+4;
int n,m,k;
const int mo=570707;
struct hashash{
struct node{
int x,y,nxt;
}a[N];
int first[mo],cnt=0;
inline void insert(int x,int y){
int r=((ll)x*M+y)%mo;
for(int i=first[r];i;i=a[i].nxt)
if(a[i].x==x&&a[i].y==y)return;
a[++cnt].x=x;a[cnt].y=y;
a[cnt].nxt=first[r];first[r]=cnt;
}
inline bool ask(int x,int y){
int r=((ll)x*M+y)%mo;
for(int i=first[r];i;i=a[i].nxt)
if(a[i].x==x&&a[i].y==y)return 1;
return 0;
}
}mp;
struct poin{
int x,y;
inline void swp(){
swap(x,y);
y=-y;
}
inline poin operator -(const poin &a)const{
return (poin){x-a.x,y-a.y};
}
inline poin operator +(const poin &a)const{
return (poin){x+a.x,y+a.y};
}
inline poin operator /(const int &a)const{
return (poin){x/a,y/a};
}
inline bool even(){
return (x&1)^(y&1);
}
inline bool check(){
return x>=0&&y>=0&&x<=n&&y<=m;
}
inline bool ispoin(){
return check()&&mp.ask(x,y);
}
}a[N];
inline int f0(){
int ret=0;
for(re int i=1,mx=min(n,m);i<=mx;i++)
ret=((ll)i*(n-i+1)*(m-i+1)+ret)%mod;
return ret;
}
inline int f1(){
int ret=0;
for(re int i=1,l,r,u,d,t;i<=k;i++){
l=a[i].y;r=m-l;
u=a[i].x;d=n-u;
t=min(l+r,u);ret=((ll)t*(t+3)/2-(t>l?(ll)(t-l)*(t-l+1)/2:0)-(t>r?(ll)(t-r)*(t-r+1)/2:0)+ret)%mod;
t=min(l+r,d);ret=((ll)t*(t+3)/2-(t>l?(ll)(t-l)*(t-l+1)/2:0)-(t>r?(ll)(t-r)*(t-r+1)/2:0)+ret)%mod;
t=min(l,u+d);ret=((ll)t*(t+3)/2-(t>u?(ll)(t-u)*(t-u+1)/2:0)-(t>d?(ll)(t-d)*(t-d+1)/2:0)+ret)%mod;
t=min(r,u+d);ret=((ll)t*(t+3)/2-(t>u?(ll)(t-u)*(t-u+1)/2:0)-(t>d?(ll)(t-d)*(t-d+1)/2:0)+ret)%mod;
ret=(ret-min(l,u)-min(u,r)-min(r,d)-min(d,l))%mod;
}
return ret;
}
inline int f2(){
int ret2=0,ret3=0,ret4=0;
poin p1,p2,p3,p4;
for(re int i=1,fl;i<=k;i++)
for(re int j=1;j<i;j++){
if(!(a[i].even()^a[j].even())){
p1=a[i]+a[j];
p2=a[i]-a[j];p2.swp();
p3=(p1+p2)/2;
p4=(p1-p2)/2;
if(p3.check()&&p4.check()){
ret2++;fl=0;
if(p3.ispoin())ret3++,fl++;
if(p4.ispoin())ret3++,fl++;
if(fl==2)ret4++;
}
}
p1=a[j]-a[i];p1.swp();
p2=a[i]+p1;
p3=a[j]+p1;
if(p2.check()&&p3.check()){
ret2++;fl=0;
if(p2.ispoin())ret3++,fl++;
if(p3.ispoin())ret3++,fl++;
if(fl==2)ret4++;
}
p2=a[i]-p1;
p3=a[j]-p1;
if(p2.check()&&p3.check()){
ret2++;fl=0;
if(p2.ispoin())ret3++,fl++;
if(p3.ispoin())ret3++,fl++;
if(fl==2)ret4++;
}
}
return ret2-ret3/3+ret4/6;
}
int main(){
n=read();m=read();k=read();
for(re int i=1,x,y;i<=k;i++){
a[i].x=x=read();a[i].y=y=read();
mp.insert(x,y);
}
cout<<((f0()-f1()+f2())%mod+mod)%mod;
return (0-0);
}
标签:JLOI,min,int,ll,ret,正方形,SHOI2016,mod 来源: https://www.cnblogs.com/aurora2004/p/12539639.html