zoukankan      html  css  js  c++  java
  • 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);
    }
    
  • 相关阅读:
    ue4 socket
    ue4动画蓝图
    localStorage 用法
    关于textarea中换行、回车、空格的识别与处理
    git忽略某些文件提交
    动态加载js文件
    H5 App页面 绝对定位 软键盘弹出时顶起底部按钮
    Android软键盘弹出时把布局顶上去的解决方法
    javascript 事件委托 和jQuery事件绑定on、off 和one
    escape()、encodeURI()、encodeURIComponent()区别详解
  • 原文地址:https://www.cnblogs.com/aurora2004/p/12539639.html
Copyright © 2011-2022 走看看