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