Fibonacci in the Pocket
題解
#include<iostream> using namespace std; int main(){ int T; scanf("%d",&T); while(T--){ string a,b; cin>>a>>b; int al=a.size(); int bl=b.size(); int suma=0; int sumb=0; for(int i=0;i<al;i++){ suma+=a[i]-'0'; } suma--; for(int i=0;i<bl;i++){ sumb+=b[i]-'0'; } printf("%d\n",(suma%3==1&&sumb%3!=1) || (suma%3!=1&&sumb%3==1) ); } return 0; }
這道題是讓求斐波那契數列任意區間段的和是奇數還是偶數,由於資料範圍很大,有\(10^{10000}\) 這麼大,所以我們不可能去求出指定區間段的斐波那契數,然後再加在一起。
通過觀察可以發現,斐波那契數列的奇偶是有規律的,斐波那契數列的奇偶排列規律為:
奇 奇 偶 奇 奇 偶 奇 奇 偶\(\cdots\)
比如:1 1 2 3 5 8 13 21 34
並且由於:
奇數+奇數=偶數
奇數+偶數=奇數
偶數+偶數=偶數
我們可以得出斐波那契數列字首和的奇偶排列順序是:
奇 偶 偶 奇 偶 偶 奇 偶 偶\(\cdots\)
比如1 1 2 3 5 8 13 21 34所對應的字首和為:
1 2 4 7 12 20 33 54 88
題目中讓求的是區間[a,b]的和是奇數還是偶數,那麼我們就要知道b的字首和是奇數還是偶數,並且還要知道(a-1)的字首和是奇數還是偶數,然後用b的字首和減去(a-1)的字首和就知道[a,b]的和是奇數還是偶數了。因為:
奇數-奇數=偶數
偶數-偶數=偶數
奇數-偶數=奇數
偶數-奇數=奇數
那麼我們如何知道(a-1)、b的字首和是奇數還是偶數呢,由於字首和的排列規律為奇 偶 偶 奇 偶 偶 奇 偶 偶\(\cdots\) ,一直在重複奇 偶 偶,那麼我們就把一個數除以3,如果餘數為1,那麼這個數的字首和就是奇數,如果餘數為2,那麼這個數的字首和就是偶數,如果餘數為0,那麼這個數的字首和就是偶數。
那麼由於a、b的資料很大,如果直接除以3的話就要用高精度,但通過進一步觀察我們可以用更簡單的方法,我們知道,一個能被3整除的數,這個數的各個數位相加的和也能被3整除,並且,一個數除以3的餘數也等於這個數的各個數位相加之和除以3的餘數。那麼,通過這樣的方法我們就不用高精度了。
在程式碼中要注意,我們要求的是(a-1)的字首和的奇偶,所以我們求出a的各個數位的和之後,要減去1,然後再去除以3,這才是(a-1)的字首和的奇偶。