SCAU1143 多少个Fibonacci数--大菲波数【杭电-HDOJ-1715】--高精度加法--Fibonacci数---大数比较

/*******对读者说(哈哈若是有人看的话23333)哈哈大杰是华农的19级软件工程新手,才疏学浅可是秉着校科联的那句“主动才会有故事”仍是大胆的作了一下建一个卑微博客的尝试,想法本身以后学到东西都记录一下
本身学的同时或许(我说或许啊哈哈)能帮到博友,若是有啥错误的话还请各位大佬在下面留言怼我,指出个人错误所在,我必定更改哈哈,通常记录的都是我对一个知识点或者是一个算法专题的笔记和一些在博客园里面看到写的好的大佬的一些借鉴
文章大部分都是在codeblocks里面写好了而后复制过来的,因此就有不少///***的,对你的产生困扰,深感抱歉
********/
//对本身说:坚持坚持坚持,总会有收获,主动就会有故事html


//分割线------------------------------------------------------------本文借鉴https://www.cnblogs.com/orchidzjl/p/4287027.html(原文)
/********************c++

                                   菲波数

 

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 12716    Accepted Submission(s): 4352


算法

Problem Description
Fibonacci数列,定义以下:
f(1)=f(2)=1
f(n)=f(n-1)+f(n-2) n>=3。
计算第n项Fibonacci数值。
 

 

Input
输入第一行为一个整数N,接下来N行为整数Pi(1<=Pi<=1000)。
 

 

Output
输出为N行,每行为对应的f(Pi)。
 

 

Sample Input
5 1 2 3 4 5
 

 

Sample Output
1 1 2 3 5
 

 思路:很纯粹的高进度加法编程

基础板子
//通常Fibonacci数在第一千多个的时候的值其实就已经达到了一百多位了,通常就10的一百屡次方了
这种高位数就天然用数组来存放也就是利用高精度加法了,而后因为是要输入一个值n,而后输出的是第
个fabonacci数的,因此就要用一个map原理
在c里面就天然的用到了二维数组来存放了,就是一维数组的下标就是这个n,而后这个一维数组的元素组成就是第
n个数了
通常遇到差很少一千多位的fabonacci数的化就要创建一个数组是a[1010][1010]
其实一千位的fabonacci数也就差很少几百位,这里创建一千多位实际上是浪费的,若是是要节省空间的化仍是
就创建一个大菲波数 ---【杭电-HDOJ-1715】
a[1010][500]就差很少了
int ans[1010][500]//装答案的/因为会用在高精度计算的函数里面也会在主函数里面用到的,因此就定义位全局变量就能够了
int c[500],d[500];因为只是在高精度函数里面用到这两个数组的因此最好仍是不要定义位全局变量了,节省空间,装第n-1个的fabonacci和第n-2个的fabonacci的,而后两个用递归来相加,用到高精度计算了
int n,m,i,j,k;//n是记录a数组的长度的,m是记录b数组长度的,ijk是用来循环的,一样的也是在函数里面哟ing到了的,不要定义位全局了
大菲波数
2019.11.25.9.18
*****************/数组

 

 1 代码:
 2 /*
 3 #include <stdio.h>
 4 #include <stdlib.h>
 5 #include<string.h>
 6 char ans[1010][500]; //优化:ans用char比用int要节省空间,而后c数组和d数组因为是要进行计算的要除以10和对10取模的因此是要定义位int
 7 //因此就要注意在类型上的转化好比若是是char变成int的化就要-'\0'若是是int变成char的化就要+'\0'
 8 void bigplus(char a[],char b[],int t) //这里的t表示的是第几个fabonacci数的,而后a和b其实就是递归里面用到的第n-1项和第n-2项的
 9 {
10 int c[500];
11 int d[500];
12 memset(c,0,sizeof(c));memset(d,0,sizeof(d));
13 int n,m,i=1,j=1,k;
14 n=strlen(a);
15 m=strlen(b);
16 for(k=n-1;k>=0;k--) //这些就没什么好解析的了,在oj是实验题里面就有高精度计算的水题了,或者在网上差一下给高精度计算的板子就会了
17 //不一样的是oj上面的是用到了一个e来做为余数的就是
18 //c[i]=(a[i]+b[i]+e)%10;
19 // e=(a[i]+b[i])/10;//其实用这个方法是更省了d这个数组的空间的了,不过我就是看到下面那个c[i+1]+=..这一步不一样而后想积累一下别的方法才写的hah1
20 
21 
22 {
23 c[i++]=a[k]-'0';
24 }
25 for(k=m-1;k>=0;k--) //开始我搞错了边了了,k=n-1而后打印出来的结果就多了不少其余的符号呢
26 {
27 d[j++]=b[k]-'0';
28 }
29 k=n>m?n:m;
30 for(i=1;i<=k;i++)
31 {
32 c[i+1]+=(c[i]+d[i])/10;
33 c[i]=(c[i]+d[i])%10;
34 }
35 if(c[k+1])
36 k+=1;
37 j=0;
38 for(i=k;i>=1;i--)
39 ans[t][j++]=c[i]+'0';
40 
41 }
42 int main()
43 {
44 memset(ans,'\0',sizeof(ans)); //因为是ans是不能够初始化为0或者是其余数组的否则以后打印的时候就会把后面的数组也打印出来了
45 // 因此就要对ans初始化是如何地方都是多是停止的地方也就是要初始化为结束符了
46 int i,n;
47 ans[1][0]='1';
48 ans[2][0]='1'; //因为左下标(二维数组)是表示的是第几个fabonacci数的,如何因为是第一个fabonacci是1,第二个也是
49 // 第二个也是1,而且他们都是个位的因此就初始化,
50 //(若是是第七个的化就是ans[7][0]=1,ans[7][1]=3,由于第7个fabonacci就是13了)只用初始化两个足够初始递归就能够了
51 for(i=3;i<=1000;i++)
52 {
53 bigplus(ans[i-1],ans[i-2],i); //每次递归都是获得一个第i个的值,因为ans是一个二维数组,可是这里传递的实际上是一维数组的指针
54 //而后用bigplus函数里面的数组a和b来接受的
55 }
56 int T;
57 scanf("%d",&T);
58 while(T--)
59 {
60 scanf("%d",&n);
61 printf("%s\n",ans[n]);
62 }
63 return 0;
64 }
65 
66 */
View Code

 

//相关的例题就是SCAUOJ里面的1143 多少个Fibonacci数
/************ide

                                   1143 多少个Fibonacci数
时间限制:500MS 内存限制:65536K
提交次数:270 经过次数:16函数

题型: 编程题 语言: G++;GCC
Description
给你以下Fibonacci 数的定义:
F1 = 1
F2 = 2
Fn = Fn-1 + Fn-2 (n >= 3)
给你两个数a与b,现要求你计算在a与b之间(包括a、b)有多少个Fibonacci 数post

 


输入格式
有多行,每行有两个数a、b,使用空格分隔,a <= b <= 10^100(即最大10的100次方)
最后一行为两个0优化


输出格式
除了最后一行,其它每一行要求输出在a与b之间的Fibonacci 数的个数,一行一个url


输入样例
10 100
1234567890 9876543210
0 0


输出样例
5
4

************/

思路:这个题目和上面板子的不一样其实就是给了一个范围,不少人可能会想到这种用到范围的都是用到莫队排序的
可是我以为这里好像不用的,若是您以为能够用到的话欢迎给我留言,我们一块儿探讨一下呀哈哈(莫队主要就是add函数和move函数,在对一维数组的一些问题上面进行算法1的
可是这里不用输出值,而是要a到b中的fabonacci数有多少个的,其实就是和ab范围内的比较,仍是要吧fabonacci算出来的
就能够用到上面的板子了
先打一个前1000项的fb表(大数加法),而后 a,b在表中找位置(大数比较),那么他们之间的个数就是了
就是建表,而后比较,而后输出个数便可

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<string.h>
  4 char ans[1010][1000];                 //仍是提醒一下吧为了优化空间的话这里吧ans二维数值是初始化为了cha类型的,
  5 void bigplus(char a[],char b[],int t)//这个高精度计算的函数和上面的板子是同样的没有变化
  6 {
  7     int c[1000],d[1000];
  8     int n,m,i=1,j=1,k;
  9     memset(c,0,sizeof(c));
 10     memset(d,0,sizeof(d));
 11     n=strlen(a);
 12     m=strlen(b);
 13     for(k=n-1;k>=0;k--)
 14         c[i++]=a[k]-'0';
 15     for(k=m-1;k>=0;k--)
 16         d[j++]=b[k]-'0';
 17     k=m>n?m:n;
 18     for(int i=1;i<=k;i++)
 19     {
 20         c[i+1]+=(c[i]+d[i])/10;
 21         c[i]=(c[i]+d[i])%10;
 22     }
 23     if(c[k+1])k+=1;
 24     j=0;
 25     for(i=k;i>=1;i--)
 26     {
 27         ans[t][j++]=c[i]+'0';
 28     }
 29 }
 30 /****以后就是要有一个高精度比较,确定不能够直接用><来比较的,由于数值都被放在了数数组里面了
 31 除非就是用c++里面的重载运算符才能够用<和>进行比较了,因此就须要吧输入的a和b这两个边界和咱们已经制好的表(也就是那个ans二维数组里面存放的值进行比较
 32 这时候就要用到另一个比较函数了我叫他bigcmp就是高精度比较,若是两个东西通过bigcmp比较以后返回的是1
 33 表示前一个大于后一个,而后返回的是-1表示的是两个相等的,若是是返回0的话就表示后一个大于前一个的
 34 *****/
 35 //这个函数的思路确定就是先比长度嘛,用strlen,长度长的天然就大,而后若是长度同样的话再从高位一项一项的比下来哈哈
 36 //感受有点麻烦,不知大佬们有啥好的方法呢?
 37 
 38 int bigcmp(char a[],char b[])
 39 {
 40     int i,n,m;
 41     n=strlen(a);
 42     m=strlen(b);
 43     if(n>m)return 1;
 44     else if(n<m)return 0;
 45 
 46     //长度同样的时候就从高位开始比,输入的范围和咱们ans数值的存放的数其实高位就是从0开始的了,
 47    // 因此在bigplus函数里面最后就是要吧c数值赋给ans的时候是要倒叙的,
 48    // 使得这个数值的最高位是存放在ans数值的0位上的,也方便了bigcmp的比较了
 49      else
 50      {
 51          for(i=0;i<n;i++)         //由于这里n=m,因此以n或者m做为边界都是能够的
 52          {
 53              if(a[i]>b[i])return 1;
 54              else if(a[i]<b[i])return 0;
 55              else                //若是仍是相等的话就继续比较下面的数便可了
 56              continue;
 57 
 58          }
 59      }
 60      return -1;                 //若是直到最后都没有比较出来的话说明这两个数是相等的
 61 }
 62 int main()
 63 {
 64     int i,j;
 65     char s1[1000],s2[1000];      //s1和s2数组是用来存放咱们要输入的两个数(就是左右范围了)
 66     memset(ans,'\0',sizeof(ans));
 67     ans[1][0]='1';
 68     ans[2][0]='2';
 69     for(i=3;i<=1000;i++)
 70         bigplus(ans[i-1],ans[i-2],i);//注意:不要写成了ans[1]和ans[2]做为第一二参数了(哈哈我刚开始就写错了)
 71     while(scanf("%s %s",s1,s2))
 72     {
 73         int cnt=0;                  //计算这个范围里面有多少个fabonacci数 像这种计数器变量的话通常都是用sum或者是cnt是count的缩写,用作计数器
 74 
 75      if(!((s1[0]-'0')||(s2[0]-'0')))break;//就是只要不是两个输入的都是0的话都是能够进行下去的,若是都是0的话就break
 76    for(i=1;i<=1000;i++)               //循环咱们刚刚制成的fabonacci表(ans数组)
 77    {                                   //再提醒一下返回值,否则你确定又翻上面看哈哈
 78                                       //比较以后返回的是1表示前一个大于后一个,而后返回的是-1表示的是两个相等的,
 79                                       //若是是返回0的话就表示后一个大于前一个
 80        if(bigcmp(ans[i],s1)==-1)      //两个相等的话
 81        {
 82            cnt=1;                      //表示的是左范围就是一个fabonacci数了,就提早的+1,而后i++就是下次就不用又比较一次了,只要出现了这个状况就break
 83           i++;
 84           break;
 85 
 86        }
 87        if(bigcmp(ans[i],s1)>0)        //若是s1小的话
 88        {
 89            cnt=0;
 90            break;
 91 
 92        }
 93    }                                 //开始我差点也搞混了,就是for里面嵌套一个if,这个if里面有一个break的话就会直接跳出最近的那个for(别笑,我刚开始好真的傻了)
 94 
 95        for(j=i;j<=1000;j++)  //若是左边界也是fabonacci的刚刚就把cnt设置为了1的,而后i++,就至关于已经把左边界是fabanacci数记录了,cnt=1了;
 96 
 97                if(bigcmp(ans[j],s2)<=0)cnt++;
 98          else
 99             break;  //用这个来结束
100        printf("%d\n",cnt);
101     }
102     return 0;
103 
104    }
View Code
相关文章
相关标签/搜索