これはすんなり。
https://yukicoder.me/problems/no/3229
問題
N人の人がおり、各人は正直者か嘘つきのいずれかである。
ここでM個の情報があり、N人の指定された部分集合に含まれる正直者が偶数であるということがわかっている。
条件を満たす、正直者の人の組み合わせは何通りか。
解法
GF(2)上でN変数M式からなる方程式があると考える。
このrankをrとすると、2^(N-r)が解となる。
rankはbitset上で掃き出し法を使い求めると、O(N*M^2)かかるが間に合う。
const int MAT=2560; bitset<MAT> S[MAT]; int V[MAT],R[MAT]; int Gauss(int R,int C,bitset<MAT> BS[MAT],int v[MAT],int r[MAT]) { int i,j,k; int nex=0; FOR(i,R) { while(nex<C) { for(j=i;j<R;j++) if(BS[j][nex]) break; if(j!=R) break; nex++; } if(nex>=C) break; swap(BS[i],BS[j]); swap(v[i],v[j]); FOR(j,R) if(i!=j && BS[j][nex]) { v[j]^=v[i]; BS[j]^=BS[i]; } nex++; } FOR(i,C) r[i]=0; int num=0; FOR(i,R) { FOR(j,C) if(BS[i][j]) break; if(j<C) { r[j]=v[i]; num++; } else if(v[i]) { return -1; } } return num; } int N,M; ll mo; void solve() { int i,j,k,l,r,x,y; string s; cin>>N>>M>>mo; FOR(i,M) { cin>>s; FOR(j,N) S[i][j]=s[j]=='1'; } x=Gauss(M,N,S,V,R); ll ret=1; FOR(i,N-x) ret=ret*2%mo; cout<<ret<<endl; }
まとめ
これは★3でもいいかも?