http://acm.hdu.edu.cn/showproblem.php?pid=5459
题意:
S(1) = c,S(2) = ff, S(3) = cff,之后S(i) = S(i-1)+S(i-2)。
现在给出n,求S(n)中任意两个c之间距离的总和。
思路:
现在假设第i-1和第i-2要合成第i个,计算S(i)的过程如下:
ans[i] = ans[i-1]+ans[i-2]+add,现在要求就是add新增的部分值。
假设S(i-2)中有2个c,下标分别为{a,b}(下标以1为起始点计)总长度为len2,S(i-1)中有3个c,下标为别为{x,y,z},总长度为len1。
那么新增的部分就是(len2-a)+x+ (len2-a)+y + (len2-a)+z +(len2-b)+x +(len2-b)+y +(len2-b)+z,也就是(len2-a+len2-b)*3 + (x+y+z)*2。
这里的话(len2-a+len2-b)就是S(i-2)中所有c点到末端的距离之和,3是S(i-1)中c的个数,x+y+z是S(i-1)中所有c点到始端的距离之和,2是S(i-2)中c的个数。
所有维护四个值进行递推,len是长度,sum是所有c点到末端的距离之和(到始端的距离之和可以通过len和sum计算出来),num是c的个数,ans是最终答案。
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int mod = 530600414; 5 const int maxn = 201314+5; 6 7 long long len[maxn],num[maxn],sum[maxn],ans[maxn]; 8 9 void init() 10 { 11 len[1] = 1, num[1] = 1, sum[1] = 1, ans[1] = 0; 12 len[2] = 2, num[2] = 0, sum[2] = 0, ans[2] = 0; 13 len[3] = 3, num[3] = 1, sum[3] = 1, ans[3] = 0; 14 len[4] = 5, num[4] = 1, sum[4] = 3, ans[4] = 0; 15 for(int i=5;i<=201314;i++) 16 { 17 len[i] = (len[i-1]+len[i-2])%mod; 18 num[i] = (num[i-1]+num[i-2])%mod; 19 ans[i] = (ans[i-1]+ans[i-2]+sum[i-1]*num[i-2]+(((len[i-2]*num[i-2]-sum[i-2])%mod)*num[i-1])%mod)%mod; 20 sum[i] = ((sum[i-2]+sum[i-1])%mod+(num[i-1]*len[i-2])%mod)%mod; 21 } 22 } 23 24 int main() 25 { 26 //freopen("in.txt","r",stdin); 27 int T; 28 int kase = 0; 29 init(); 30 scanf("%d",&T); 31 while(T--) 32 { 33 int n; 34 scanf("%d",&n); 35 printf("Case #%d: %lld ",++kase,ans[n]); 36 } 37 return 0; 38 }