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\n",++kase,ans[n]);
36     }
37     return 0;
38 }