• [POI2015]CZA


    [POI2015]CZA 

    p很小,讨论

    p=0。。。

    p=1。。。

    p=2:n-1放左或者放右两种情况,剩下怎么放是固定的,模拟然后判断即可

    p=3:

    正着做要状压,类似放书和排座位那些题,考虑以某个顺序加入元素,不断扩充出整个环

    不妨从n开始往下加,其实只用考虑i,i-1,i-2和要放的i-3的关系。i-3只能放在这三个的两个的中间,

    所以这中间不能再有之前的i+1,i+2这种了。

    而且区分左右还要记录顺逆

    f[i][0/1][2^3]前i个,顺逆,相邻能不能放(是否紧相邻)

    然后枚举放哪里转移,之后i会固定,看会不会和i-1,i-2,i-3冲突

    转移时候大力分类讨论

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=1000000+5;
    const int mod=1e9+7;
    int n,k,p;
    int no[N][7];//0:-3; 1:-2 ; 2:-1 ; 3:0 ; 4:1 ; 5:2 ; 6:3
    int add(int x,int y){
        return x+y>=mod?x+y-mod:x+y;
    }
    void sol0(){
        if(n==1) puts("1");
        else puts("0");
    }
    void sol1(){
        if(n==1||(n==2&&k==0)) puts("1");
        else puts("0");    
    }
    int a[N];
    void sol2(){
        if(n<=2){
            if(n==1||(n==2&&k==0)) puts("1");
            else puts("0");
            return;
        }
        int ans=0;
        a[1]=n;
        for(reg x=n-1,i=2;x>0;++i,x-=3) a[i]=x;
        for(reg x=n-2,i=n;x>0;--i,x-=2) a[i]=x;
        bool fl=true;
        for(reg i=1;i<n;++i){
            if(no[a[i]][a[i+1]-a[i]+3]) fl=false;
        }
        if(no[a[n]][a[1]-a[n]+3]) fl=false;
        if(fl) ++ans;
        
        a[1]=n;
        for(reg x=n-2,i=2;x>0;++i,x-=2) a[i]=x;
        for(reg x=n-1,i=n;x>0;--i,x-=2) a[i]=x;
        fl=true;
        for(reg i=1;i<n;++i){
            if(no[a[i]][a[i+1]-a[i]+3]) fl=false;
        }
        if(no[a[n]][a[1]-a[n]+3]) fl=false;
        if(fl) ++ans;
        printf("%d",ans);
    }
    int f[N][2][8];
    int dis(int x,int y){
        return y-x+3;
    }
    int mk(int s1,int s2,int s3){
        return s3*4+s2*2+s1;
    }
    void calc(int i,int j,int s){//add i-1
        int now=f[i][j][s];
        int s1=s&1,s2=(s>>1)&1,s3=(s>>2)&1;
        if(i!=2){
            if(j==0){//shun
                if(s1){
                    if(s3){
                     if(no[i][dis(i,i+2)]==0&&no[i+2][dis(i+2,i-1)]==0) f[i-1][j][mk(s2,0,1)]=add(f[i-1][j][mk(s2,0,1)],now);
                    }
                    else{
                     if(no[i+2][dis(i+2,i-1)]==0) f[i-1][j][mk(s2,0,1)]=add(f[i-1][j][mk(s2,0,1)],now);
                    }
                }
                if(s2){
                    if((s1==0||no[i+2][dis(i+2,i+1)]==0)&&(s3==0||no[i][dis(i,i+2)]==0)) f[i-1][j^1][mk(0,1,1)]=add(f[i-1][j^1][mk(0,1,1)],now);
                }
                if(s3){
                    if((s1==0||no[i+2][dis(i+2,i+1)]==0)&&(no[i-1][dis(i-1,i+2)]==0)) f[i-1][j][mk(s2,1,0)]=add(f[i-1][j][mk(s2,1,0)],now);
                }
            }
            else{//j==1
                if(s1){
                    if(s3){
                     if(no[i+2][dis(i+2,i)]==0&&no[i-1][dis(i-1,i+2)]==0) f[i-1][j][mk(s2,0,1)]=add(f[i-1][j][mk(s2,0,1)],now);
                    }
                    else{
                     if(no[i-1][dis(i-1,i+2)]==0) f[i-1][j][mk(s2,0,1)]=add(f[i-1][j][mk(s2,0,1)],now);
                    }
                }
                if(s2){
                    if((s1==0||no[i+1][dis(i+1,i+2)]==0)&&(s3==0||no[i+2][dis(i+2,i)]==0)) f[i-1][j^1][mk(0,1,1)]=add(f[i-1][j^1][mk(0,1,1)],now);
                }
                if(s3){
                    if((s1==0||no[i+1][dis(i+1,i+2)]==0)&&(no[i+2][dis(i+2,i-1)]==0)) f[i-1][j][mk(s2,1,0)]=add(f[i-1][j][mk(s2,1,0)],now);
                }
            }
        }else{//las 
            if(j==0){
                if(s1){
                    if((s3==0||no[i][dis(i,i+2)]==0)&&(no[i+2][dis(i+2,i-1)]==0)&&(no[i-1][dis(i-1,i+1)]==0)&&(s2==0||no[i+1][dis(i+1,i)]==0)){
                        f[i-1][j][mk(0,0,0)]=add(f[i-1][j][mk(0,0,0)],now);
                    }
                }
                if(s2){
                    if((s3==0||no[i][dis(i,i+2)]==0)&&(s1==0||no[i+2][dis(i+2,i+1)]==0)&&(no[i+1][dis(i+1,i-1)]==0&&no[i-1][dis(i-1,i)]==0)){
                        f[i-1][j^1][mk(0,0,0)]=add(f[i-1][j^1][mk(0,0,0)],now);
                    }
                }
                if(s3){
                    if((s1==0||no[i+2][dis(i+2,i+1)]==0)&&(s2==0||no[i+1][dis(i+1,i)]==0)&&(no[i][dis(i,i-1)]==0&&no[i-1][dis(i-1,i+2)]==0)){
                        f[i-1][j][mk(0,0,0)]=add(f[i-1][j][mk(0,0,0)],now);
                    }
                }
            }
            else{
                if(s1){
                    if((s3==0||no[i+2][dis(i+2,i)]==0)&&(no[i-1][dis(i-1,i+2)]==0)&&(no[i+1][dis(i+1,i-1)]==0)&&(s2==0||no[i][dis(i,i+1)]==0)){
                        f[i-1][j][mk(0,0,0)]=add(f[i-1][j][mk(0,0,0)],now);
                    }
                }
                if(s2){
                    if((s3==0||no[i+2][dis(i+2,i)]==0)&&(s1==0||no[i+1][dis(i+1,i+2)]==0)&&(no[i-1][dis(i-1,i+1)]==0&&no[i][dis(i,i-1)]==0)){
                        f[i-1][j^1][mk(0,0,0)]=add(f[i-1][j^1][mk(0,0,0)],now);
                    }
                }
                if(s3){
                    if((s1==0||no[i+1][dis(i+1,i+2)]==0)&&(s2==0||no[i][dis(i,i+1)]==0)&&(no[i-1][dis(i-1,i)]==0&&no[i+2][dis(i+2,i-1)]==0)){
                        f[i-1][j][mk(0,0,0)]=add(f[i-1][j][mk(0,0,0)],now);
                    }
                }
            }
        }
    }
    void sol3(){
        if(n<=2){
            if(n==1||(n==2&&k==0)) puts("1");
            else puts("0");
            return;
        }
        if(n==3){
            int ans=0;
            if(no[n][dis(n,n-1)]==0&&no[n-1][dis(n-1,n-2)]==0&&no[n-2][dis(n-2,n)]==0) ++ans;
            if(no[n][dis(n,n-2)]==0&&no[n-2][dis(n-2,n-1)]==0&&no[n-1][dis(n-1,n)]==0) ++ans;
            printf("%d",ans);
            return ;
        }
        f[n-2][1][7]=1;f[n-2][0][7]=1;
        for(reg i=n-2;i>=2;--i){
            for(reg s=0;s<8;++s){
                if(f[i][0][s]) calc(i,0,s);
                if(f[i][1][s]) calc(i,1,s);
            }
        }
        int ans=0;
        for(reg s=0;s<8;++s){
            ans=add(ans,add(f[1][0][s],f[1][1][s]));
        }
        printf("%d",ans);
    }
    int main(){
        rd(n);rd(k);rd(p);
        int x,y;
        for(reg i=1;i<=k;++i){
            rd(x);rd(y);
            if(abs(x-y)<=p){
                no[x][y-x+3]=1;
            }
        }
        if(p==0) sol0();
        else if(p==1) sol1();
        else if(p==2) sol2();
        else sol3();
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2019/3/3 10:02:45
    */
  • 相关阅读:
    从无到有实现登录功能以及thinkphp怎么配置数据库信息
    Navicat软件中mysql中int、bigint、smallint和tinyint的区别、布尔类型存储以及乱码问题的解决
    ThinkPHP实现对数据库的增删改查
    ListView实现点击事件以及总结
    仿迅雷播放器教程 -- 提取exe资源(12)
    仿迅雷播放器教程 -- C++ windows界面库对比(11)
    仿迅雷播放器教程 -- C++ 100款开源界面库 (10)
    仿迅雷播放器教程 -- C++界面制作方法的对比 (9)
    仿迅雷播放器教程 -- 权威界面库对比 (8)
    仿迅雷播放器教程 -- 十年经验大牛对MFC的认识 (7)
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10483445.html
Copyright © 2020-2023  润新知