Fibonacci前缀子串个数

该博客探讨了一道编程问题,涉及计算给定序列中包含的Fibonacci前缀子序列的数量。博主首先介绍了问题背景和限制条件,然后详细阐述了解决思路:构建Fibonacci数列并进行哈希,利用动态规划(dp)数组记录以每个Fibonacci数为结尾的子序列数量。在遍历输入序列时,对于Fibonacci数,答案加上其前一个Fibonacci数对应子序列数量,并更新当前dp值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:(http://hihocoder.com/problemset/problem/1239)给定一个序列,问该序列中蕴含的fibonacci前缀子序列有多少个。如长度为4的序列1122,答案为5,分别为1、1、11、112、112。题目保证输入中的每个数不大于100000.

思路:先构造不大于100000的fibonacci序列,并且将数字之于下标hash一下。dp[i]表示第i个fibonacci数为最后一个数的子序列个数。然后从左往右扫一遍输入串,如果该数不是fibonacci数,那么不管。如果是1,特判;如果是其他的fibonacci数,那么答案加上前一个fibonacci数为终止数的子序列个数(通过hash),并且更新当前的dp。如果解释的不清楚,见代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#define M 100000
#define N 1000000
int s[N],f[M],hash[M+5];
int t[M];
int n;
void init(){
    memset(t, 0, sizeof(t));
    memset(hash,0,sizeof(hash));
    f[0] = f[1] = 1;
    for(int i = 2;;i++){
        f[i] = f[i-1]+f[i-2];
        if(f[i] > M)
            break;
        hash[f[i]] = i;
    }
}
int main(){
    init();
    scanf("%d",&n);
    for(int i = 0;i<n;i++)
        scanf("%d",&s[i]);
    int res = 0;
    for(int i = 0;i<n;i++){
        if(s[i] == 1){
            res += t[0]+1;
            t[1] += 
题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了。例如企鹅,只会卖萌向游客要吃的。为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学习算法。 某天,园长给动物们讲解 KMP 算法。 园长:“对于一个字符 S,它的长度为 L。我们可以在 O(L) 的时间内,求出一个名为 next 的组。有谁预习了 next 组的含义吗?” 熊猫:“对于字符 S 的前 i 个字符构成的子串,既是它的后缀又是它的前缀的字符中(它本身除外),最长的长度记作 next[i]。” 园长:“非常好!那你能举个例子吗?” 熊猫:“例 S 为 abcababc,则 next[5]=2。因为S的前5个字符为 abcab,ab 既是它的后缀又是它的前缀,并且找不到一个更长的字符满足这个性质。同理,还可得出 next[1]=next[2]=next[3]=0,next[4]=next[6]=1,next[7]=2,next[8]=3。” 园长表扬了认真预习的熊猫同学。随后,他详细讲解了如何在 O(L) 的时间内求出 next 组。 下课前,园长提出了一个问题:“KMP 算法只能求出 next 组。我现在希望求出一个更强大 num 组一一对于字符 S 的前 i 个字符构成的子串,既是它的后缀同时又是它的前缀,并且该后缀与该前缀不重叠,将这种字符量记作 num[i]。例如 S 为 aaaaa,则 num[4]=2。这是因为S的前 4 个字符为 aaaa,其中 a 和 aa 都满足性质‘既是后缀又是前缀’,同时保证这个后缀与这个前缀不重叠。而 aaa 虽然满足性质‘既是后缀又是前缀’,但遗憾的是这个后缀与这个前缀重叠了,所以不能计算在内。同理,num[1]=0,num[2]=num[3]=1,num[5]=2。” 最后,园长给出了奖励条件,第一个做对的同学奖励巧克力一盒。听了这句话,睡了一节课的企鹅立刻就醒过来了!但企鹅并不会做这道题,于是向参观动物园的你寻求帮助。你能否帮助企鹅写一个程序求出num组呢? 特别地,为了避免大量的输出,你不需要输出 num[i] 分别是多少,你只需要输出所有 (num[i]+1) 的乘积,对 10 9 +7 取模的结果即可。 输入格式 第 1 行仅包含一个正整 n,表示测试据的组。 随后 n 行,每行描述一组测试据。每组测试据仅含有一个字符 S,S 的定义详见题目描述。据保证 S 中仅含小写字母。输入文件中不会包含多余的空行,行末不会存在多余的空格。 输出格式 包含 n 行,每行描述一组测试据的答案,答案的顺序应与输入据的顺序保持一致。对于每组测试据,仅需要输出一个整,表示这组测试据的答案对 10 9 +7 取模的结果。输出文件中不应包含多余的空行。
最新发布
07-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值