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