
给定两个整数A和B,并定义S序列为:
S0S_{0}S0=A
S1S_{1}S1=B
SiS_{i}Si=|Si−1S_{i-1}Si−1 - Si−2S_{i-2}Si−2| 对于i > 2
要求算出S序列里有多少种数字
刚开始的时候由于并不熟悉这类题型,思路走错了。
我原本认定这类题型应该和gcd有关系,所以想的是用gcd去求,但是实际上这个想法不全面。
后来做了好久不断摸索才发现这道题不应该用gcd的想法去想。
手动模拟一下我们会发现S序列呈现出一种周期性,会周期性出现同一个数字,让后其他数字不断减去这个数
也就是说有这样一个数字x,序列里有不比A大的k*x + tmp的正整数数列.
同时我们还会发现,对于同一组A,B结果是一样的,不管谁大谁小。
那么我们完全可以假定前面的数字一直比后面的数字大,然后推出来这样子的结论:
我们可以假设A = k * B + tmp,如果此时的B是周期性出现的那个数字,那么k*B + tmp的数列里的数字都在S序列中,出现次数就是k,最终会变成tmp,并且变成tmp的时候tmp的位置肯定和B相邻,所以我们完全可以让前面的数字作为B,后面的数字为tmp
那么代码基本部分就完成了,但是要注意一些特殊情况:
A=B=0的时候答案为1
A和B中有且只有一个0的时候答案为2
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int MOD=1e9+7;
const int N=1000100;
void init() {
}
int a[N];
int tim;
void solve() {
init();
int x,y;
cin>>x>>y;
//一些模拟部分数据如下
//10 2 8 6 2 4 2 2 0
//2 10 8 2
//7 4 3 1 2 1 1 0
//6 9 3 6 3 3 0
//12 18 6 12 6 6 0
//100 7 93 86 7 79 72 7 65 58 7 51 44 7 37 30 7 23 16 7 9 2 7
//15 3 12 9 3 6 3 3 0
//21 3 18 15 3 12 9 3 6 3 3 0
//3 21 18 3 15 12 3 9 6 3 3 0
//22 3 19 16 3 13 10 3 7 4 3 1 2 1 1 0
//3 22 19 3 16 13 3 10 7 3 4 1 3
//23 3 20 17 3 14 11 3 8 5 3 2 1 1 0
//6 3 3 0
//11 4 7 3 4 1 3 2 1 1 0
//7 4 3 1 2 1 1 0
//100 60 40 20 20 0
//100 61 59 2 57 55 2
//100 62 58 4 54 50 4
if(x==0 && y==0) {
cout<<"Case #"<<tim<<": "<<1<<"\n";
return ;
}
else if(x==0 && y!=0) {
cout<<"Case #"<<tim<<": "<<2<<"\n";
return ;
}
else if(x!=0 && y==0) {
cout<<"Case #"<<tim<<": "<<2<<"\n";
return ;
}
else {
int sum=1;
int tmp=1;
while(tmp) {
sum += x/y;
tmp = x%y;
x = y;
y = tmp;
}
cout<<"Case #"<<tim<<": "<<sum<<"\n";
}
}
signed main() {
//ios::sync_with_stdio(false);
//cin.tie(0);
//cout.tie(0);
int t=1;
cin>>t;
while(t--) {
tim++;
solve();
}
return 0;
}
总结:这道题我最开始没有往构造k*B+tmp这方面去想是我在这种连续相减的类似题目不熟悉,之前见过的连续相减的题目是用gcd去解决的,所以我先入为主认为这道题应该用gcd来求,但结论而言我最开始的想法是错误的,所以说之后要清楚还有这样一种可能性,就是构造一个等差数列,而这个数列里的数字全部都会出现。

京公网安备 11010502036488号