https://vjudge.net/problem/Kattis-dancecircle
题意:
n长01圈,告诉你n个区间的1的数量奇偶性,求方案数。
解析:
假设不是圈,告诉你区间 的奇偶性,相当于知道了 和 两个前缀的奇偶性是否相同。而我们可以假设全部的奇偶性,将越过端点的区间化作没有越过端点的区间。若左端点为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*/