標籤:block [1] names 左移 max 練習題 cci std 運算
題目描述
NowCoder最近在研究一個數列:
- F(0) = 7
- F(1) = 11
- F(n) = F(n-1) + F(n-2) (n≥2)
他稱之為NowCoder數列。請你幫忙確認一下數列中第n個數是否是3的倍數。
輸入描述:
輸入包含多組資料。
每組資料包含一個整數n,(0≤n≤1000000)。
輸出描述
對應每一組輸入有一行輸出。
如果F(n)是3的倍數,則輸出“Yes”;否則輸出“No”。
---
輸入例子:
0
1
2
3
4
5
輸出例子:
No
No
Yes
No
No
No
---
題目分析
這是一個特殊初始條件的Fibonacci sequence.
1.初始條件n的值比較小,可以直接枚舉每個F(n)的值,然後輸入n查詢:
#include <iostream> #include <cstdio> using namespace std; int main (){ int n; int *a=new int[N]; a[0]=7; a[1]=11; for(int i=2;i<N;i++) a[i]=a[i-2]%3+a[i-1]%3; while(~scanf("%d", &n)){ cout<<a[n]<<endl; if(a[n]%3==0) cout<<"Yes"<<endl; else cout<<"No"<<endl; } return 0; }
2.可以尋找到規律:(牛客網友“我要過pat”提供)
這個真牛批,想不到還有這種規律。那Fibonacci數列是否有相似的規律呢?
#include <iostream> using namespace std;int main (){ int n; while(cin>>n){ if((n-2)%4==0) cout<<"Yes"<<endl; else cout<<"No"<<endl; } return 0; }
3.用矩陣快速冪來求解,這題n的範圍比較小(0≤n≤1000000)所以用第1種方法可以不逾時求解,但是,倘若n很大,達到(1<=n<=1000,000,000,000,000,000)這個範圍,那麼顯而易見,必定逾時。而且根本開不到那麼大的數組。學校的演算法課,有另外一題類似的,可以思考一下:
藉此思路,用矩陣快速冪計算,稍微修改下就可以了。
#include <iostream> #include <cstdio> #include <cstring> #define N 3#define maxn 2 using namespace std; struct Matrix{ long long a[maxn][maxn]; void init(){ //初始化為單位矩陣 memset(a, 0, sizeof(a)); for(int i=0;i<maxn;++i){ a[i][i] = 1; } } }; //矩陣乘法 Matrix mul(Matrix a, Matrix b){ Matrix ans; for(int i=0;i<maxn;++i){ for(int j=0;j<maxn;++j){ ans.a[i][j] = 0; for(int k=0;k<maxn;++k){ ans.a[i][j] += a.a[i][k] * b.a[k][j]; ans.a[i][j] %= N; } } } return ans; } //矩陣快速冪 Matrix qpow(Matrix a, long long n){ Matrix ans; ans.init(); while(n){ if(n&1) ans = mul(ans, a); a = mul(a, a); n /= 2; } return ans; } int main (){ long long n; while(~scanf("%lld", &n)){ Matrix a; a.a[0][0] = 1; a.a[0][1] = 1; a.a[1][0] = 1; a.a[1][1] = 0; long long s0=7,s1=11; if (n>1) { Matrix ans= qpow(a, n-1); long long res=ans.a[0][0]*s1+ans.a[0][1]*s0; // printf("%lld",res); if(res%3==0) cout<<"Yes"<<endl; else cout<<"No"<<endl; } else cout<<"No"<<endl; } return 0; }
測評網站真的噁心,有時候迴圈輸入用"cin>>"就可以,有時候又逾時。。。得改"成~scanf("%lld", &n)"。另外一開始沒想到對中間結果對3模數,導致數值過大溢出。用到unsigned long long 都不夠。。。
PS:檢測一個數被3整除的演算法
1.檢測一個數能否被3整除----位元運算
如果所有的偶數位出現1的次數為 even_count, 奇數位出現1的次數為 odd_count,兩者只差如果是3的倍數,那麼這個數就是3倍數。
2.不用除法和求模運算,判斷一個數能否被3整除
現在給出一個數a,假設它能被3整除,結果是b,即a=3*b,那麼從二進位乘法運算判斷出,b的最低位與a的最低位一定是相同的,從而得到了b的最低位,將這個位左移1位變成次低位,那麼a的次低位以上的位元減去這個位後在次低位上的結果一定是b的次低位。以此類推可以求出b的各個位元,如果最後能完成對b的各位的計算,那麼a能夠被3整除,否則不能被3整除。
那麼演算法原理是什麼呢?
PAT乙級(Basic Level)練習題-NowCoder數列總結