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
相關文章
相關標籤/搜索