まだ本戦は解いてませんが。
https://beta.atcoder.jp/contests/cf18-relay-open/tasks/relay2018_e
問題
円形に並んだN個のイスに、W匹の狼とF匹の狐が座る。(W+F=Nである)
一部のイスは、どちらが座るか確定している。
余った席に狼と狐が座る組み合わせ全通りに対し、隣接する積同士で狼と狐が座るケースが何通りあるか、和を求めよ。
解法
2つの隣接するイス毎に、「狼・狐」または「狐・狼」になるケースを考えよう。
残りのイスの狼・狐の組み合わせは簡単に求められるのでそれらを足し合わせればよい。
string S; int N,X,Y; ll mo=1000000007; ll comb(ll N_, ll C_) { const int NUM_=1400001; static ll fact[NUM_+1],factr[NUM_+1],inv[NUM_+1]; if (fact[0]==0) { inv[1]=fact[0]=factr[0]=1; for (int i=2;i<=NUM_;++i) inv[i] = inv[mo % i] * (mo - mo / i) % mo; for (int i=1;i<=NUM_;++i) fact[i]=fact[i-1]*i%mo, factr[i]=factr[i-1]*inv[i]%mo; } if(C_<0 || C_>N_) return 0; return factr[C_]*fact[N_]%mo*factr[N_-C_]%mo; } void solve() { int i,j,k,l,r,x,y; string s; cin>>S>>X; N=S.size(); Y=N-X; FORR(c,S) { if(c=='W') X--; if(c=='F') Y--; } S+=S; ll ret=0; FOR(i,N) { char c1=S[i]; char c2=S[i+1]; // WF x=X,y=Y; if(c1=='?') x--; if(c1=='F') x=-1; if(c2=='?') y--; if(c2=='W') y=-1; if(x>=0 && y>=0) ret+=comb(x+y,x); //FW x=Y,y=X; if(c1=='?') x--; if(c1=='W') x=-1; if(c2=='?') y--; if(c2=='F') y=-1; if(x>=0 && y>=0) ret+=comb(x+y,x); } cout<<ret%mo<<endl; }
まとめ
ここら辺まではまだ割と簡単。