題目大意:
字符串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;
}