1. 程式人生 > 實用技巧 >Fibonacci in the Pocket

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)的字首和的奇偶。