HDU 5459 Jesus Is Here (递推,组合数学)

时间:2023-03-09 08:53:58
HDU 5459 Jesus Is Here (递推,组合数学)

有点麻烦的递推,递推的原则:向小的问题方向分解,注意边界。

字符串的递推式为

HDU 5459 Jesus Is Here (递推,组合数学)

定义f为Si中的总方案数

首先可以得到

fi=fi-1+fi-2+组合(si-2,si-1)

然后考虑Si-2和Si-1之间的组合

HDU 5459 Jesus Is Here (递推,组合数学)

为了得到小的问题,进行拆分

HDU 5459 Jesus Is Here (递推,组合数学)

为了以后表示的方便和逻辑上的清晰,把Si~Si之间的组合总长度定义出来

HDU 5459 Jesus Is Here (递推,组合数学)

因为这里的si-2和si-2的中间还有一段Si-3

所以其组合总长度就可以表示为

HDU 5459 Jesus Is Here (递推,组合数学)

Ci表示Si中cff出现的次数,Li表示Si的长度

定义一个函数ccl

HDU 5459 Jesus Is Here (递推,组合数学)

最后还剩下一个部分Si-2和Si-3

定义

HDU 5459 Jesus Is Here (递推,组合数学)

至此,总方案已经可以表示出来

HDU 5459 Jesus Is Here (递推,组合数学)

然后再从顶往下的逐步细化

考虑g(i)的计算

HDU 5459 Jesus Is Here (递推,组合数学)

这里面也有个递推,首先可以得到

HDU 5459 Jesus Is Here (递推,组合数学)

为了方便再定义一个函数

HDU 5459 Jesus Is Here (递推,组合数学)

显然这个容易计算得多

剩下的组合也可以表示出来了

HDU 5459 Jesus Is Here (递推,组合数学)

最后一部分f12(i)

HDU 5459 Jesus Is Here (递推,组合数学)

#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 ;
}