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




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章