Dance Circle(染色 奇偶性)

https://vjudge.net/problem/Kattis-dancecircle

题意:

n长01圈,告诉你n个区间的1的数量奇偶性,求方案数。

解析:

假设不是圈,告诉你区间 [ l , r ] [l,r] 的奇偶性,相当于知道了 l 1 l-1 r r 两个前缀的奇偶性是否相同。而我们可以假设全部的奇偶性,将越过端点的区间化作没有越过端点的区间。若左端点为0,就知道了r这个前缀的奇偶性。

没有关联的前缀之间互不影响。有关联的若不冲突,又分为有没有确定两种,方案数分别为1和2。

代码:

/*
 *  Author : Jk_Chen
 *    Date : 2020-03-08-14.33.55
 */
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
#define debug(x) cerr<<#x<<" = "<<x<<'\n'
const LL mod=1e9+7;
const int maxn=2e5+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
    while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/

int l[maxn],r[maxn],f[maxn];
struct node{
    int to,f;// 0 same 1 different
};
vector<node>V[maxn];
int F[maxn],Fnow[maxn]; // real , now
bool hav_same,hav_dif,cant;
bool vis[maxn];
void dfs(int p,int pos){
    vis[p]=1;
    Fnow[p]=pos;
    if(F[p]!=-1){
        if(F[p]==Fnow[p])hav_same=1;
        else hav_dif=1;
    }
    for(auto Q:V[p]){
        int sta=pos;
        if(Q.f==1)sta=1-sta;
        if(vis[Q.to]){
            if(sta!=Fnow[Q.to]){
                cant=1;return;
            }
        }
        else{
            dfs(Q.to,sta);
        }
    }
}

int main(){
    int n=rd;
    rep(i,0,n-1){
        l[i]=rd,r[i]=rd,f[i]=rd;
    }

    LL ans=0;

    // all is even
    LL Ans=1;
    rep(i,0,n-1)V[i].clear();
    mmm(F,-1);
    mmm(Fnow,-1);
    mmm(vis,0);

    F[n-1]=0;
    rep(i,0,n-1){
        int L=i-l[i],R=i+r[i];
        if(R-L+1==n){
            L=0,R=n-1;
        }
        if(L==0){
            if(F[R]==-1)F[R]=f[i];
            else if(F[R]==f[i])continue;
            else{
                Ans=0;break;
            }
        }
        else if(L>0&&R<=n-1){
            V[R].pb({L-1,f[i]});
            V[L-1].pb({R,f[i]});
        }
        else if(L<0){
            L+=n;
            swap(L,R);
            L++,R--;
            V[R].pb({L-1,f[i]});
            V[L-1].pb({R,f[i]});
        }
        else{
            R-=n;
            swap(L,R);
            L++,R--;
            V[R].pb({L-1,f[i]});
            V[L-1].pb({R,f[i]});
        }
    }
    rep(i,0,n-1){
        if(!vis[i]){
            cant=hav_same=hav_dif=0;
            dfs(i,0);
            if(cant){
                Ans=0;break;
            }
            if(hav_dif&&hav_same){
                Ans=0;break;
            }
            if(!hav_dif&&!hav_same){
                Ans=Ans*2%mod;
            }
        }
    }
    ans=Ans;


    // all is odd
    Ans=1;
    rep(i,0,n-1)V[i].clear();
    mmm(F,-1);
    mmm(Fnow,-1);
    mmm(vis,0);

    F[n-1]=1;
    rep(i,0,n-1){
        int L=i-l[i],R=i+r[i];
        if(R-L+1==n){
            L=0,R=n-1;
        }
        if(L==0){
            if(F[R]==-1)F[R]=f[i];
            else if(F[R]==f[i])continue;
            else{
                Ans=0;break;
            }
        }
        else if(L>0&&R<=n-1){
            V[R].pb({L-1,f[i]});
            V[L-1].pb({R,f[i]});
        }
        else if(L<0){
            L+=n;
            swap(L,R);
            L++,R--;
            V[R].pb({L-1,1-f[i]});
            V[L-1].pb({R,1-f[i]});
        }
        else{
            R-=n;
            swap(L,R);
            L++,R--;
            V[R].pb({L-1,1-f[i]});
            V[L-1].pb({R,1-f[i]});
        }
    }
    rep(i,0,n-1){
        if(!vis[i]){
            cant=hav_same=hav_dif=0;
            dfs(i,0);
            if(cant){
                Ans=0;break;
            }
            if(hav_dif&&hav_same){
                Ans=0;break;
            }
            if(!hav_dif&&!hav_same){
                Ans=Ans*2%mod;
            }
        }
    }

    ans=(ans+Ans)%mod;
    printf("%lld\n",ans);

    return 0;
}

/*_________________________________________________________end*/
发布了773 篇原创文章 · 获赞 345 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/104738322
今日推荐