题解:P10101 [ROIR 2023 Day 2] 一个普通的字符串问题
Solution
一道普通的组合计数问题。
考虑现在有三种点,
我们需要保证这三种颜色的连续段两两相邻的次数满足题目所给的条件。再次基础上,如果我们知道三种颜色分别出现了多少次,就可以具体分配内部
后者是平凡的,关注一下前面的问题。
先考虑计算
显然我们还可以判断,那种点的最后一个是没有出边的,具体表现为这种点的总出边比这种点的出现次数少
如果只有一种点出现,答案是
一种很自然的想法是,我们可以把每个点的所有出边赋上颜色,表示它走向另外两个点中的哪一个。每一种序列都会对应唯一一个颜色的赋值方式,但是有的颜色赋值方式可能是不合法的。
假设
这样写几个组合数就好了。
#include<bits/stdc++.h>
#define int long long
#define ffor(i,a,b) for(int i=(a);i<=(b);i++)
#define roff(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
const int MAXN=2e6+10,MOD=1e9+7;
int op,n,m,q,frac[MAXN],inv[MAXN];
int qpow(int base,int p) {
int ans=1;
while(p) {
if(p&1) ans=ans*base%MOD;
base=base*base%MOD,p>>=1;
}
return ans;
}
int C(int u,int d) {
if(u>d) return 0;
return frac[d]*inv[u]%MOD*inv[d-u]%MOD;
}
string S;
int cnt[3][3];
signed main() {
freopen("str.in","r",stdin);
freopen("str.out","w",stdout);
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
m=2000000;
frac[0]=1;
ffor(i,1,m) frac[i]=frac[i-1]*i%MOD;
inv[m]=qpow(frac[m],MOD-2);
roff(i,m-1,0) inv[i]=inv[i+1]*(i+1)%MOD;
cin>>op>>q;
ffor(i,1,q) {
cin>>S,n=S.size(),S="&"+S;
if(n==1) {
cout<<3<<'\n';
continue ;
}
int flg=1;
memset(cnt,0,sizeof(cnt));
ffor(j,2,n) cnt[S[j-1]-'a'][S[j]-'a']++,flg&=(S[j]==S[1]);
if(flg) {
cout<<1<<'\n';
continue ;
}
int ans=0;
ffor(s,0,2) {
int col[3]={0,0,0},in[3]={0,0,0},out[3]={0,0,0};
col[s]++;
ffor(c1,0,2) ffor(c2,0,2) if(c1!=c2) in[c2]+=cnt[c1][c2],out[c1]+=cnt[c1][c2],col[c2]+=cnt[c1][c2];
int flg=0,psl=0,ed=0;
ffor(c,0,2) {
if(out[c]!=col[c]&&out[c]+1!=col[c]) flg=1;
if(out[c]!=col[c]) psl++,ed=c;
}
if(out[s]==0) continue ;
if(flg||psl!=1) continue ;
int mul=C(cnt[0][1],out[0])*C(cnt[1][0],out[1])%MOD*C(cnt[2][0],out[2])%MOD;
if(ed==0) mul=(mul-C(cnt[0][1],out[0])*C(cnt[1][0],out[1]-1)%MOD*C(cnt[2][0],out[2]-1)%MOD)%MOD;
else if(ed==1) mul=(mul-C(cnt[0][1],out[0]-1)*C(cnt[1][0],out[1])%MOD*C(cnt[2][1],out[2]-1)%MOD)%MOD;
else mul=(mul-C(cnt[0][2],out[0]-1)*C(cnt[1][2],out[1]-1)%MOD*C(cnt[2][0],out[2])%MOD)%MOD;
ffor(c,0,2) {
if(col[c]==0) {
if(cnt[c][c]!=0) mul=0;
continue ;
}
mul=mul*C(col[c]-1,cnt[c][c]+col[c]-1)%MOD;
}
ans=(ans+mul)%MOD;
}
cout<<(ans%MOD+MOD)%MOD<<'\n';
}
return 0;
}
我怎么想不到