题意:定义斐波那契字符串为:

  • $f_1 = $ "a"
  • \(f_2 =\) "b"
  • \(f_n = f_{n-1} + f_{n-2}, \, n > 2\)

例如,$f_3 = $ “ba”。

有\(m\)次询问,第\(i\)次给出一个字符串\(s_i\),问\(s_i\)在\(f_n\)中的出现次数。

\(m \leq 10^4, \, n \leq 10^{18}, \, \sum|s_i| \leq 10^5\)

主要问题在与\(f_p\)与\(f_{p-1}\)拼接时,\(f_p\)的某个后缀与\(f_{p-1}\)的某个前缀可能恰好拼成\(s_i\),即产生额外的出现次数。当\(|f_p|\)与\(|f_{p-1}|\)都大于等于\(|s_i|\)时,这个数值就等于\(f_{n}\)长度为\(|s_i|-1\)的后缀与\(f_{p-1}\)长度为\(|s_i|-1\)的前缀组成的字符串中\(s_i\)的出现次数。

我们设\(f_{p-1}\)长度为\(|s_i|-1\)的前缀为\(a\),长度为\(|s_i|-1\)的后缀为\(b\),\(f_{p}\)长度为\(|s_i|-1\)的前缀为\(a\),长度为\(|s_i|-1\)的后缀为\(c\)。我们观察发现:

| | 长度为\(|s_i|-1\)的前缀 | 长度为\(|s_i|-1\)的后缀 | 产生额外贡献的字符串 |

| ------------ | --------------------- | --------------------- | -------------------- |

| \(f_{p-1}\) | \(a\) | \(b\) | |

| \(f_p\) | \(a\) | \(c\) | \(ca\) |

| \(f_{p+1}\) | \(a\) | \(b\) | \(ba\) |

| \(f_{p+2}\) | \(a\) | \(c\) | \(ca\) |

| \(f_{p+3}\) | \(a\) | \(b\) | \(ba\) |

| …… | …… | …… | …… |

| \(f_{p+2k}\) | \(a\) | \(c\) | \(ca\) |

| \(f_{p+2k+1}\) | \(a\) | \(b\) | \(ba\) |

我们设\(s_i\)在\(ca\)中的出现次数为\(n_c\),在\(ba\)中的出现次数为\(n_b\),\(O_n\)表示\(s_i\)在\(f_{n+p}\)中的出现次数。

那么,容易得到

\[O_n = O_{n-1} + O_{n-2} + \begin{cases} n_c, & \text {if $ n\mod 2 = 0$} \\ n_b, & \text{if $n \mod 2 = 1$}\end{cases}
\]

考虑拆分贡献,即设\(A_n\),\(B_n\),\(C_n\)分别表示\(f_n\)中,\(s_i\)在\(f_p\)和\(f_{p+1}\)中的出现次数,在所有\(ba\)中的出现次数,在所有\(ca\)中的出现次数。那么,我们有

  • \(O_n = A_n + B_n \times n_b + C_n \times n_c\)
  • \(A_n = A_{n-1} + A_{n-2}\)
  • \(B_n = B_{n-1} + B_{n-2} + [n \mod 2 = 1] = B_{n-1} + B_{n-2} + \frac {1 - (-1)^n} {2}\)
  • \(C_n = C_{n-1} + C_{n-2} + [n \mod 2 = 0] = C_{n-1} + C_{n-2} + \frac {1 + (-1)^n} {2}\)
  • \(B_0 = B_1 = C_0 = C_1 = 0\)

其中,\(A_n\)在我们计算出\(A_0\)和\(A_1\)后,用矩阵快速幂得到。故我们只用考虑\(B_n\)和\(C_n\)这两个类似的数列。

通过使用OEIS或其他的数列求解方法,我们得到\(B_n = F_{n-1} - \frac {1+(-1)^n}{2}\),以及\(C_n = F_{n} - \frac{1 - (-1)^n}{2}\)。其中,\(F_n\)为第\(n\)个斐波那契数。它们同样可以用矩阵快速幂求出。

时间复杂度\(O(\sum|s_i| + m \log n )\)。

  1. #include <bits/stdc++.h>
  2. #define int long long
  3. using namespace std;
  4. const int N = 30010, MAX = 200000, MOD = 1000000007;
  5. string fib[N];
  6. int n,m,len,cnt,lef[N],nex[MAX + 10];
  7. char tmp[MAX + 10];
  8. string a,b,c,tp;
  9. struct matrix {
  10. int mat[3][3];
  11. matrix() {
  12. memset(mat,0,sizeof mat);
  13. }
  14. matrix operator * (const matrix& x) const {
  15. matrix ret = matrix();
  16. for (int k = 1 ; k <= 2 ; ++ k)
  17. for (int i = 1 ; i <= 2 ; ++ i)
  18. for (int j = 1 ; j <= 2 ; ++ j)
  19. (ret.mat[i][j] += 1ll * mat[i][k] * x.mat[k][j] % MOD) %= MOD;
  20. return ret;
  21. }
  22. };
  23. matrix bas;
  24. matrix power(matrix a,int b) {
  25. matrix ret = matrix();
  26. ret.mat[1][1] = ret.mat[2][2] = 1;
  27. while (b) {
  28. if (b&1) ret = ret * a;
  29. a = a * a;
  30. b >>= 1;
  31. }
  32. return ret;
  33. }
  34. int getfib(int x) {
  35. matrix ret = power(bas,x);
  36. return ret.mat[1][2];
  37. }
  38. int getnum() {
  39. int ret = 0;
  40. for (int i = 0, j = 0 ; i < (int)tp.length() ; ++ i) {
  41. while (j >= 0 && tmp[j+1] != tp[i])
  42. j = nex[j];
  43. ++ j;
  44. if (j == len) ++ ret, j = nex[j];
  45. }
  46. return ret;
  47. }
  48. int solve() {
  49. nex[0] = -1;
  50. for (int i = 2, j = 0 ; i <= len ; ++ i) {
  51. while (j >= 0 && tmp[j+1] != tmp[i])
  52. j = nex[j];
  53. nex[i] = ++j;
  54. }
  55. int p = lower_bound(lef+1,lef+cnt+1,len) - lef;
  56. ++ p;
  57. if (n <= p+1) {
  58. tp = fib[n];
  59. return getnum();
  60. }
  61. a = fib[p].substr(0,len-1);
  62. b = fib[p].substr(lef[p] - len+1,len-1);
  63. c = fib[p+1].substr(lef[p+1] - len+1,len-1);
  64. int nb, nc, n0, n1, pos = n - p, ret = 0;
  65. tp = b + a;
  66. nb = getnum();
  67. tp = c + a;
  68. nc = getnum();
  69. tp = fib[p];
  70. n0 = getnum();
  71. tp = fib[p+1];
  72. n1 = getnum();
  73. (ret += 1ll * (getfib(pos) - (pos&1)) * nc % MOD) %= MOD;
  74. (ret += 1ll * (getfib(pos-1) - 1 + (pos&1)) * nb % MOD) %= MOD;
  75. matrix sta = matrix();
  76. sta.mat[1][1] = n1;
  77. sta.mat[1][2] = sta.mat[2][1] = n0;
  78. sta = sta * power(bas,pos);
  79. (ret += sta.mat[1][2]) %= MOD;
  80. ret = (ret % MOD + MOD) % MOD;
  81. return ret;
  82. }
  83. signed main() {
  84. fib[1] = "a";
  85. fib[2] = "b";
  86. for (int i = 3 ; ; ++ i) {
  87. fib[i] = fib[i-1] + fib[i-2];
  88. lef[i] = fib[i].length();
  89. cnt = i;
  90. if (lef[i-1] >= MAX) break;
  91. }
  92. bas.mat[1][1] = bas.mat[1][2] = bas.mat[2][1] = 1;
  93. cin >> n >> m;
  94. for (int i = 1 ; i <= m ; ++ i) {
  95. scanf("%s",tmp+1);
  96. len = strlen(tmp+1);
  97. cout << solve() << endl;
  98. }
  99. return 0;
  100. }

小结:用一种不大简单的做法做出了这道题。思考时间过长,并且依赖网站来求解数列,这是做此题时体现出的不足之处。

【做题】CF177G2. Fibonacci Strings——思维+数列的更多相关文章

  1. 【做题】NOWCODER142A Ternary String——数列&欧拉定理

    题意:你有一个长度为\(n\),且仅由012构成的字符串.每经过一秒,这个字符串所有1后面会插入一个0,所有2后面会插入一个1,然后会删除第一个元素.求这个字符串需要多少秒变为空串,对\(10^9+7 ...

  2. noip做题记录+挑战一句话题解?

    因为灵巧实在太弱辽不得不做点noip续下命QQAQQQ 2018 积木大赛/铺设道路 傻逼原题? 然后傻逼的我居然检查了半天是不是有陷阱最后花了差不多一个小时才做掉我做过的原题...真的傻逼了我:( ...

  3. CodeM美团点评编程大赛复赛 做题感悟&题解

    [T1] [简要题意]   长度为N的括号序列,随机确定括号的方向:对于一个已确定的序列,每次消除相邻的左右括号(右左不行),消除后可以进一步合并和消除直到不能消为止.求剩下的括号的期望.\(N \l ...

  4. (luogu1704)寻找最优美做题曲线 [TPLY]

    寻找最优美做题曲线 题目链接:https://www.luogu.org/problemnew/show/P1704 题目大意: 求包含指定点的最长不降子序列(严格递增) 题解 首先我们发现 一个序列 ...

  5. AtCoder Grand Contest 1~10 做题小记

    原文链接https://www.cnblogs.com/zhouzhendong/p/AtCoder-Grand-Contest-from-1-to-10.html 考虑到博客内容较多,编辑不方便的情 ...

  6. 课后选做题-MyOD

    课后选做题-MyOD od命令的了解 功能 od命令用于将指定文件内容以八进制.十进制.十六进制.浮点格式或ASCII编码字符方式显示,通常用于显示或查看文件中不能直接显示在终端的字符.od命令系统默 ...

  7. BJOI做题记录

    BJOI做题记录 终于想起还要做一下历年省选题了2333 然而咕了的还是比做了的多2333 LOJ #2178. 「BJOI2017」机动训练 咕了. LOJ #2179. 「BJOI2017」树的难 ...

  8. 【做题记录】AtCoder AGC做题记录

    做一下AtCoder的AGC锻炼一下思维吧 目前已做题数: 75 总共题数: 239 每一场比赛后面的字母是做完的题,括号里是写完题解的题 AGC001: ABCDEF (DEF) AGC002: A ...

  9. FJOI2017前做题记录

    FJOI2017前做题记录 2017-04-15 [ZJOI2017] 树状数组 问题转化后,变成区间随机将一个数异或一,询问两个位置的值相等的概率.(注意特判询问有一个区间的左端点为1的情况,因为题 ...

随机推荐

  1. 1.23 codeforces div3 C.Nice Garland

    You have a garland consisting of nn lamps. Each lamp is colored red, green or blue. The color of the ...

  2. 《大话设计模式》c++实现 状态模式

    状态模式包含如下角色: Context: 环境类 State: 抽象状态类 ConcreteState: 具体状态类 2)适用场景: a)状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂 ...

  3. HTML&CSS书写规范

    第一部分:HTML书写规范: 1.1 HTML整体结构: 1.1.1:HTML基础设施: 文档以"<!DOCTYPE...>"首行顶格开始,推荐使用"< ...

  4. 爬虫万金油,一鹅在手,抓遍全球:goose 简介!

    GOOSE 现已弃用 经过多年的服务,GOOSE接口和支持它的MySQL数据现已弃用 . 在我们进行替换的同时,我们建议寻找一般查询功能的用户在http://rdf.geneontology.org上 ...

  5. Maven依赖中的scope详解,在eclipse里面用maven install可以编程成功,到服务器上用命令执行报VM crash错误

    Maven依赖中的scope详解 项目中用了<scope>test</scope>在eclipse里面用maven install可以编译成功,到服务器上用命令执行报VM cr ...

  6. AtCoder Beginner Contest 045 C - たくさんの数式 / Many Formulas

    Time limit : 2sec / Memory limit : 256MB Score : 300 points Problem Statement You are given a string ...

  7. POJ 1018 Communication System (动态规划)

    We have received an order from Pizoor Communications Inc. for a special communication system. The sy ...

  8. Django框架----分页器(paginator)

    Django的分页器(paginator) view.py from django.shortcuts import render,HttpResponse # Create your views h ...

  9. hiho一下 第145周

    题目1 : 智力竞赛 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi.小Ho还有被小Hi强拉来的小Z,准备组队参加一个智力竞赛.竞赛采用过关制,共计N个关卡.在第i ...

  10. yii2项目中运行composer 过程中遇到的问题

    问题1: Your requirements could not be resolved to an installable set of packages 则表明 未安装fxp/composer-a ...