当前位置:   article > 正文

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

蓝桥杯练习系统(算法训练)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<iostream>
  2. #include<string>
  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;j<s3.length();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<iostream>
  2. #include<string>
  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;j<s3.length();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;j<s3.length();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;j<s3.length();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<iostream>
  2. #include<string>
  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;j<s3.length();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了。。这个方法还是不太严谨,虽然它通过了吧。希望可以给你带来一些思路,如果有更好的方法欢迎在评论区留言或私信我。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/244573
推荐阅读
相关标签
  

闽ICP备14008679号