有点麻烦的递推,递推的原则:向小的问题方向分解,注意边界。
字符串的递推式为
定义f为Si中的总方案数
首先可以得到
fi=fi-1+fi-2+组合(si-2,si-1)
然后考虑Si-2和Si-1之间的组合
为了得到小的问题,进行拆分
为了以后表示的方便和逻辑上的清晰,把Si~Si之间的组合总长度定义出来
因为这里的si-2和si-2的中间还有一段Si-3
所以其组合总长度就可以表示为
Ci表示Si中cff出现的次数,Li表示Si的长度
定义一个函数ccl
最后还剩下一个部分Si-2和Si-3
定义
至此,总方案已经可以表示出来
然后再从顶往下的逐步细化
考虑g(i)的计算
这里面也有个递推,首先可以得到
为了方便再定义一个函数
显然这个容易计算得多
剩下的组合也可以表示出来了
最后一部分f12(i)
#include<bits/stdc++.h>
using namespace std; #define PB push_back
#define MP make_pair
#define fi first
#define se second typedef long long ll; const int N = +;
ll f[N], c[N], l[N], g[N];
const int Mod = ; inline ll f21(int i) { return f[i]-f[i-]-f[i-]; }
inline ll ccl(int i,int j,int k) { return c[i]*c[j]%Mod*l[k]; }
inline ll f12(int i) { return g[i-]+f21(i-)+ccl(i-,i-,i-); }//用到i-3 //#define LOCAL
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif
l[] = ; l[] = ;
l[] = ; l[] = ;
c[] = ; c[] = ;
g[] = ; g[] = ;
for(int i = ; i <= ; i++){
l[i] = (l[i-]+l[i-])%Mod;
c[i] = (c[i-]+c[i-])%Mod;
f[i] = (f[i-]+f[i-]+g[i-]+ccl(i-,i-,i-)+f12(i-)+Mod)%Mod;//用到i-4,所以从5开始
g[i] = (g[i-]+g[i-]+ccl(i-,i-,i-)+ccl(i-,i-,i-)+f12(i)+f21(i)+ccl(i-,i-,i))%Mod;//用到f[i]和l[i],所以f[i]l[i]在前面
}
int T, kas = ; scanf("%d",&T);
while(T--){
int n; scanf("%d",&n);
printf("Case #%d: %I64d\n",++kas,f[n]);
}
return ;
}