Codeforces 176B Word Cut
Description
题面
题目大意:给定两个串A,B,每一次可以翻转A串的两个部分,如A=XY->YX,问恰好经过K次操作变成B串的方案数
Solution
需要注意到一个问题:本质不同的串最多只有 \(n-1\) 个
可以把A看成一个环,每一次翻转相当于改变一个起点
于是我们可以归类为两种串:1.原串 2.非原串
原串可以产生\(n-1\)个非原串,非原串可以产生 \(n-2\) 个非原串和 \(1\) 个原串
注意到:变成所有的非原串的方案数都是一样的
因为非原串中并不一定所有的都等于B,所以还需要枚举B等于哪几个非原串,判定加上几个非原串的贡献
设 \(f[i][0/1]\) 表示产生原串的方案数和产生非原串的方案数
\(f[i][0]=f[i-1][1]*(n-1)\)
\(f[i][1]=f[i-1][0]+(n-2)*f[i-1][1]\)
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,mod=1e9+7;
int ans=0,f[N][2],K,n;char a[N],b[N];
inline bool check(int x){
for(int i=1;i<=n;i++){
if(a[x]!=b[i])return false;
x++;if(x==n+1)x=1;
}
return true;
}
int main(){
scanf("%s%s%d",a+1,b+1,&K);
n=strlen(a+1);
f[0][0]=1;
for(int i=1;i<=K;i++){
f[i][0]=1ll*f[i-1][1]*(n-1)%mod;
f[i][1]=(f[i-1][0]+1ll*f[i-1][1]*(n-2))%mod;
}
for(int i=1;i<=n;i++){
if(check(i)){
if(i==1)ans=(ans+f[K][0])%mod;
else ans=(ans+f[K][1])%mod;
}
}
cout<<ans<<endl;
return 0;
}