其他分享
首页 > 其他分享> > JLOI/SHOI2016方

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