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;
}
posted @ 2018-02-22 14:49  PIPIBoss  阅读(280)  评论(0编辑  收藏  举报