HDU 5459 Jesus Is Here(递推)

题目大意:

字符串s1=c,s2=ff

s[n]=s[n-2]+s[n-1](n>=3)

给出n,求s[n]中任意两个cff之间距离之和。


分析:

设所求为f[n]。

则必然有f[n]=f[n-2]+f[n-1]+a[n]。

关键就是求新增加的部分a[n]是多少。

可以发现任意两个cff之间的距离之和即任意两个c之间的距离之和(s[n]中任意两个c之间的距离都必然是>=2的,即不会出现cfcff这样的串)。


对于s[5]=cffffcff,s[6]=ffcffcffffcff,计算新增加的值,即考虑计算s[5]中每一个c到s[6]中每一个c的距离之和。

可以先计算一下s[5]中的每一个c到s[5]末尾的距离,分别为8和3。

然后计算s[6]中每一个c到s[6]开始位置的距离,也即c的下标,分别为2、5、10

于是新增加的值为(8+2)+(8+5)+(8+10)+(3+2)+(3+5)+(3+10)=3*(8+3)+2*(2+5+10)


记len[n]为s[n]的长度,num[n]为s[n]中c的个数,sum[n]为s[n]中c的下标之和。

则a[n]=num[n-1]*(num[n-2]*len[n-2]-sum[n-2])+num[n-2]*sum[n-1] ,(说明:s[n-2]中每一个c到s[n-2]末尾的距离可通过用s[n-2]的总长减去当前c的坐标得到)


容易得到:

len[n]=len[n-2]+len[n-1]

num[n]=num[n-2]+num[n-1]

sum[n]=sum[n-2]+sum[n-1]+len[n-2]*c[n-1]



#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef __int64 LL;
#define mod 530600414
#define maxn 201315
LL f[maxn],num[maxn],sum[maxn],len[maxn];

void init()
{
    f[3]=f[4]=0;
    len[3]=3,num[3]=1,sum[3]=0;
    len[4]=5,num[4]=1,sum[4]=2;
    for(int i=5;i<maxn;++i)
    {
        len[i]=(len[i-2]+len[i-1])%mod;
        num[i]=(num[i-2]+num[i-1])%mod;
        sum[i]=((sum[i-2]+sum[i-1])%mod+len[i-2]*num[i-1]%mod)%mod;
        LL a=(num[i-1]*((num[i-2]*len[i-2]%mod-sum[i-2]+mod)%mod)%mod+num[i-2]*sum[i-1]%mod)%mod;
        f[i]=((f[i-2]+f[i-1])%mod+a)%mod;
    }
}

int main()
{
   int T,ca,n;
   init();
   scanf("%d",&T);
   for(ca=1;ca<=T;++ca)
   {
       scanf("%d",&n);
       printf("Case #%d: ",ca);
       printf("%I64d\n",f[n]);
   }
   return 0;
}




你可能感兴趣的:(HDU 5459 Jesus Is Here(递推))