一道递推题
感觉这种题找规律对我来说好困难……还是慢慢想吧
题意:s1 = c,s2 = ff,s3 = cff,……s[i] = s[i - 2] + s[i - 1]
从s5开始(s5 = cffffcff),出现了两个cff, 相隔为5,那么输出5
s6 = ffcffcffffcff,输出所有cff之间距离的和,为3+5+8 = 16
s[i],i<=201314,输出ans[i]
思路:由题意发现了一些类斐波那契数列,字符串s[i] = s[i - 2] + s[i - 1],字符串长度len[i] = len[i - 1] + len[i - 2], 字符串中c的个数num[i] = num[i - 1] + num[i - 2]。
然后需要记录字符串中c的位置和,以第一个字符的位置为1,那么sum[i] = sum[i - 1] + sum[i - 2] + len[i - 2] * num[n - 1]。
关于ans,可以这样考虑, ans[i] = ans[i - 1] + ans[i - 2] + ?
?为i - 1和i - 2中cff之间的距离之和,首先算i - 1中所有c到i - 2的字符串串首的距离,既num[i - 1] * len[i - 2] + sum[i - 1]…………一式
由于i - 2中有num[i - 2]个c,则一式需要乘上num[i - 2],既num[i - 1] * len[i - 2] * num[i - 2] + num[i - 2] * sum[i - 1] …………二式
实际上i - 1中的c只需要移到i - 2中c的位置,于是二式需要减去sum[n - 2] * num[n - 1]
化简可得ans[i] = ans[i - 1] + ans[i - 2] + (len[i - 2] * num[i - 2] - sum[i - 2]) * num[i - 1] + sum[i - 1] * num[i - 2]
然后注意这四个数组都要开long long,不然会溢出,取模要对每一个都取。
代码:
1 #include <iostream> 2 #include <cstdio> 3 4 using namespace std; 5 6 const int N = 201314 + 1; 7 const int mod = 530600414; 8 typedef long long ll; 9 10 ll len[N], num[N], sum[N], ans[N]; 11 12 int main() 13 { 14 int t, n; 15 16 cin>>t; 17 len[0] = 1, len[1] = 2, len[2] = 3, len[3] = 5, len[4] = 8, len[5] = 13; 18 num[0] = 1, num[1] = 0, num[2] = 1, num[3] = 1, num[4] = 2, num[5] = 3; 19 sum[0] = 1, sum[1] = 0, sum[2] = 1, sum[3] = 3, sum[4] = 7, sum[5] = 20; 20 ans[4] = 5, ans[5] = 16; 21 for(int i = 5; i < N - 1; i ++ ){ 22 len[i+1] = (len[i] + len[i-1]) % mod; 23 num[i+1] = (num[i] + num[i-1]) % mod; 24 sum[i+1] = (sum[i] + sum[i-1] + len[i-1] * num[i]) % mod; 25 ans[i+1] = (ans[i] + ans[i-1] + (((len[i-1] * num[i-1] - sum[i-1]) % mod) * num[i]) % mod + (sum[i] * num[i-1]) % mod) % mod; 26 27 } 28 int flag = 0; 29 while(t -- ){ 30 flag ++ ; 31 scanf("%d", &n); 32 printf("Case #%d: ", flag); 33 printf("%d\n", ans[n-1]); 34 } 35 return 0; 36 }
写题解整理了一遍思路(
感觉清楚多了
原文地址:https://www.cnblogs.com/moomight/p/11426463.html