• [bzoj4558][JLoi2016]方【容斥原理】【计数】


    【题目链接】
      http://www.lydsy.com/JudgeOnline/problem.php?id=4558
    【题解】
      显然可以从总状态中减去不合法的状态。
      对于不合法的状态,可以用容斥原理即:有一个点不合法-有两个点不合法+有三个点不合法-有四个点不合法。
      对于总状态,枚举所占位置的大小,再枚举偏移程度即可统计。
      对于有一个点不合法:枚举它所占的矩形的外框,即横平竖直的矩形,然后分它在四个角上(未发生偏移),在(四条边上)的方案数。
      对于有两个点不合法,枚举这两个点,判断是否可行。
      对于有三个点不合法,枚举两个点,判断第三个点是否合法,因为一个矩形会被枚举三遍(两条边+一条对角线)所以最后要除以3。
      四个点和三个点同理,最后要除以6。

    /* --------------
        user Vanisher
        problem bzoj-4558
    ----------------*/
    # include <bits/stdc++.h>
    # define    ll      long long
    # define    inf     0x3f3f3f3f
    # define    P1      1000000
    # define    P2      1
    # define    N       2010
    # define    Key     999983
    # define    P       100000007
    using namespace std;
    int f[Key];
    struct node{
        ll data,next;
    }e[N];
    ll read(){
        ll tmp=0, fh=1; char ch=getchar();
        while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
        while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
        return tmp*fh;
    }
    int place;
    ll cutx[N],cuty[N],t1,t2,t3,t4,n,m,k,ans;
    void join(ll x){
        ll y=x%Key;
        e[++place].data=x;
        e[place].next=f[y];
        f[y]=place;
    }
    ll query(ll x, ll y){
        ll now=x*P1+y*P2, pp=now%Key;
        for (int ed=f[pp]; ed!=0; ed=e[ed].next)
            if (e[ed].data==now)
                return 1;
        return 0;
    }
    ll query1(ll x, ll y){
        return min(x-1,y-1);
    }
    ll query2(ll x, ll y, ll nowy){
        ll k=x-1, t=min(y-nowy,k), p=min(nowy-1,k);
        ll cut=min(k-p,t);
        return p*cut+max(((p-1)+(k-t))*((p-1)-(k-t)+1)/2,0ll);
    }
    void solve(ll x1, ll y1, ll x2, ll y2){
        if (x1>0&&x1<=n&&x2>0&&x2<=n&&y1>0&&y1<=m&&y2>0&&y2<=m){
            t2++;
            ll tmp=query(x1,y1)+query(x2,y2);
            t3+=tmp; t4+=(tmp==2);
        }
    }
    void doit(ll x1, ll y1, ll x2, ll y2){
        ll dx=x2-x1, dy=y2-y1;
        solve(x1-dy,y1+dx,x2-dy,y2+dx);
        solve(x1+dy,y1-dx,x2+dy,y2-dx);
        if ((dx+dy)%2==0){
            dy=(dx+dy)>>1; dx-=dy;  
            solve(x1+dx,y1+dy,x2-dx,y2-dy); 
        }
    }
    int main(){
        n=read()+1, m=read()+1, k=read();
        for (ll i=1; i<=k; i++){
            cutx[i]=read()+1, cuty[i]=read()+1;
            join(cutx[i]*P1+cuty[i]*P2);
        }
        for (ll i=2; i<=min(n,m); i++)
            ans=(ans+(n-i+1)*(m-i+1)%P*(i-1))%P;
        for (ll i=1; i<=k; i++){
            t1=(t1+query1(cutx[i],cuty[i])+query1(n-cutx[i]+1,cuty[i]))%P;
            t1=(t1+query1(cutx[i],m-cuty[i]+1)+query1(n-cutx[i]+1,m-cuty[i]+1))%P;
            t1=(t1+query2(cutx[i],m,cuty[i])+query2(n-cutx[i]+1,m,cuty[i]))%P;
            t1=(t1+query2(cuty[i],n,cutx[i])+query2(m-cuty[i]+1,n,cutx[i]))%P;
            for (ll j=1; j<i; j++)
                doit(cutx[j],cuty[j],cutx[i],cuty[i]);
        }
        printf("%lld
    ",((ans-t1+t2-t3/3+t4/6)%P+P)%P);
        return 0;
    }
    
  • 相关阅读:
    API接口智能化测试探索与实践
    程序员的社会地位
    程序员五六年能存100万,你说你焦虑个啥!!!
    苹果公司宣布:公司内部的员工有权讨论自己的工作条件和薪酬
    男子股票账户突然多了一个亿!结果……
    你选择双休还是单休?
    PAL制式和NTSC制式的定义及区别(转)
    javascript入门系列演示·三种弹出对话框的用法实例(转)
    sink相关
    Ubuntu下安装gsteditor
  • 原文地址:https://www.cnblogs.com/Vanisher/p/9135992.html
Copyright © 2020-2023  润新知