• 蓝桥杯练习系统(算法训练)ALGO-980 斐波那契串


    资源限制

    内存限制:256.0MB   C/C++时间限制:10.0s   Java时间限制:30.0s   Python时间限制:50.0s

    问题描述

      斐波那契串由下列规则生成:
      F[0] = "0";
      F[1] = "1";
      F[n] = F[n-1] + F[n-2] (n≥2,+表示连接)
      给出一个由0和1构成的串S和一个数n,求出F[n]中S出现的次数。

    输入格式

      第一行一个数n。
      第二行一个01串S。

    输出格式

      答案。

    样例输入

    96
    10110101101101

    样例输出

    7540113804746346428

    数据规模和约定

      n≤263-1,子串长≤10000,答案≤263-1。

    暴力,特别暴力的方法,显然是不行的,但是为了方便理解:(n<=30还是可以的,但这里n很大)

    1. #include
    2. #include
    3. using namespace std;
    4. int main(){
    5. long long int n;
    6. string s1="0",s2="1",s3,s;
    7. scanf("%d",&n);
    8. cin>>s;
    9. for(int i=2;i<=n;i++){
    10. s3=s1+s2;
    11. s1=s2;
    12. s2=s3;
    13. }
    14. //求个数
    15. long long int cnt=0;
    16. for(int j=0;jlength();j++){
    17. if(s3.substr(j,s.length())==s){
    18. cnt++;
    19. }
    20. }
    21. printf("%lld\n",cnt);
    22. return 0;
    23. }

    以下是100分的代码:

    1. #include
    2. #include
    3. using namespace std;
    4. int flag;
    5. long long int L1,L2,L;//成斐波那契数列的答案,L1为第一个不为0的个数,L2为第2个不为0的个数
    6. long long int x;//第一个不为0的位置
    7. int main(){
    8. long long int n;
    9. string s1="0",s2="1",s3,s;
    10. scanf("%lld",&n);
    11. cin>>s;
    12. for(int i=2;i<=n;i++){
    13. s3=s1+s2;
    14. s1=s2;
    15. s2=s3;
    16. for(int j=0;jlength();j++){
    17. if(s3.substr(j,s.length())==s){
    18. flag=1;
    19. break;
    20. }
    21. }
    22. if(flag==1){
    23. x=i;
    24. break;
    25. }
    26. }
    27. for(int j=0;jlength();j++){
    28. if(s3.substr(j,s.length())==s){
    29. L1++;
    30. }
    31. }
    32. s3=s1+s2;
    33. s1=s2;
    34. s2=s3;
    35. for(int j=0;jlength();j++){
    36. if(s3.substr(j,s.length())==s){
    37. L2++;
    38. }
    39. }
    40. for(int i=x+2;i<=n;i++){
    41. L=L1+L2+1;//规律
    42. L1=L2;
    43. L2=L;
    44. }
    45. printf("%lld\n",L);
    46. return 0;
    47. }

     思路:s串的个数成类似于斐波那契数列的规律。

    虽然前面提到的暴力方法不能求解n很大的情况,但是前25个绝对没问题,根据暴力方法输出前25个来找规律:

    假设串s="10110101101101"

    1. #include
    2. #include
    3. using namespace std;
    4. int main(){
    5. string s1="0",s2="1",s3,s;
    6. int n;
    7. scanf("%d",&n);
    8. cin>>s;
    9. for(int i=2;i<=n;i++){
    10. s3=s1+s2;
    11. //求个数
    12. int cnt=0;
    13. for(int j=0;jlength();j++){
    14. if(s3.substr(j,s.length())==s){
    15. cnt++;
    16. }
    17. }
    18. printf("n=%d:%d个\n",i,cnt);
    19. s1=s2;
    20. s2=s3;
    21. }
    22. return 0;
    23. }

    可以发现,从含有串s个数不为0的F[n]之后,如F[7],F[8]之后,有以下规律:

    F(i)=F(i-1)+F(i-2)+1 

    因此只需找到第一个含s串的位置x,求出个数L1,然后求出位置x+1的个数L2,之后根据规律即可求出所有。

    //但是这个规律好像也不大对,当s=“01”时:

    第三个数是前两个数的和,不需要+1了。。这个方法还是不太严谨,虽然它通过了吧。希望可以给你带来一些思路,如果有更好的方法欢迎在评论区留言或私信我。

  • 相关阅读:
    Spring Boot+Vue3前后端分离实战wiki知识库系统之电子书管理功能开发
    Linux下查找JDK默认安装路径
    记录--vue中动态引入图片为什么要是require, 你不知道的那些事
    for循环,给标题内容累计打标签
    数据库三范式
    使用Airflow实现简单的工作流调度-大数据培训
    〖Python 数据库开发实战 - MySQL篇㉔〗- 数据插入操作 - NSERT语句
    【LeetCode】哈希表题解汇总
    武汉理工大学 Python程序设计第八章测验
    【DL with Pytorch】第 3 章 :使用 DNN 的分类问题
  • 原文地址:https://blog.csdn.net/m0_73801775/article/details/136604196