hdu5459 Jesus Is Here 递推

hdu5459 Jesus Is Here
这道题题解上写的难度系数2 ,但是我们比赛的时候并没有写出来 -  -
思路:
考虑s[n-2]与s[n-1]合并的时候应该需要什么,需要什么我们就求什么
例如:s[5]+s[6]  我们把每个cff往后连算一对,假设我们已经把s[5]和s[6]的答案已经求出来了
那么s[5]中的2个cff需要连到s[6]中的3个cff上,也就是说s[6]中的所有cff与最前端的距离的和需要被算2次,s[5]中所有cff到最后端的距离和要被多算3次
所以我们需要知道:所有cff前缀长度和pf cff的个数cn 串的长度len 所有cff后缀长度和sf  这四个函数
分别求出来:
设f为斐波那契数列

cn(n)=f(n-2)
len(n)=f(n+1)
pf(n)=cn(n-1)*len(n-2)+sf(n-1)+sf(n-2)
sf(n)=len(n)*cn(n)-sf(n)
ans(n)=cn(n-1)*sf(n-2)+cn(n-2)*pf(n-1)+ans(n-1)+ans(n-2)
想化简得化简一下即可,还是太菜了啊TAT

附:
1 2 3 4 5 6
c ff cff ffcff cffffcff ffcffcffffcff
所有cff前缀长度和pf 0 0 0 2 5 17
cff的个数cn 0 0 1 1 2 3
串的长度len 1 2 3 5 8 13
所有cff后缀长度和sf 0 0 3 3 11 22

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 300000;
const long long MOD=530600414;
long long f[MAXN];
long long g[MAXN];
long long s[MAXN];
long long mod(long long a)
{
    a=a%MOD;
    if(a<0) a+=MOD;
    return a;
}
void init()
{
    ///all function start from 1;
    f[0]=f[1]=f[2]=1;
    for(int i=3;i<MAXN;i++)
        f[i]=mod(f[i-1]+f[i-2]);

    g[0]=g[1]=g[2]=g[3]=0;
    for(int i=4;i<MAXN;i++)
        g[i]=mod(g[i-1]+g[i-2]+mod(f[i-3]*f[i-1]));

    s[0]=s[1]=s[2]=s[3]=s[4]=0;

    for(int i=5;i<MAXN;i++)
        s[i]=s[i-1]+s[i-2]+mod(f[i-3]*mod(f[i-1]*f[i-4]-g[i-2]))+mod(f[i-4]*g[i-1]),
        s[i]=mod(s[i]);
}

int main()
{
    init();
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        printf("Case #%d: %lld\n",cas++,s[n]);
    }
    return 0;
}


你可能感兴趣的:(ACM)