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)的前缀和的奇偶。

posted @ 2020-08-29 09:31  ice--cream  阅读(179)  评论(0编辑  收藏  举报