题目意思:
你是一只青蛙,你在一个无限大的二维平面,如果你当前的位置为(x,y),那么你可以跳到(x +LCM(x,y),y)或者(x, y + LCM(x,y))。现在给你终点(ex,ey), 问有多少个起点可以按照这种走法走到这个点。
题目思路:
设
x=n∗k,y=m∗k,gcd(x,y)=k,也就是说
gcd(n,m)=1。
那么我们可以得到
LCM(x,y)=x∗y/k=n∗k∗m∗k/k=n∗m∗k。
则
(x,y)可以表示为(n∗k,m∗k),他可以去
(n∗(m+1)∗k,m∗k)或者
(n∗k,(n+1)∗m∗k)。
我们发现
gcd(n∗(m+1)∗k,m∗k)=gcd(n∗k,(n+1)∗m∗k)=k。
因为
gcd(n,m)=1,gcd(n,n+1)=1,gcd(m,m+1)=1。
那么
gcd(n∗(m+1),m)=gcd(n,(n+1)∗m)=1。
推到这里,我们得到启发,我们可以逆推了,假如当前我们在(x,y),表示成
(n∗(m+1)∗k,m∗k)或者
(n∗k,(n+1)∗m∗k),我们很容易通过x和y的大小关系,判断他是
(n∗(m+1)∗k,m∗k)还是
(n∗k,(n+1)∗m∗k)。而且我们发现青蛙运动的过程中,x,y坐标的gcd是不变的。
那么我们可以开始逆推,我们假设
x>y,那么就是
(n∗(m+1)∗k,m∗k),可以走到他的点只有
(n∗k,m∗k)。
因为过程中,x,y坐标的gcd是不变的,所以我们一开始的就把他除掉,这样我们只需要关心当前 x % (y + 1) ==0,判断这个点是否还有点可以走到他。处理完,这条路径上有点的数量加上原始点本身就是答案。
代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main() {
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int t; cin >> t;
for(int ca = 1; ca <= t; ca++) {
LL x, y;
cin >> x >> y;
if(x < y) swap(x, y);
LL g = __gcd(x, y);
x /= g; y /= g;
LL ans = 1;
while(x % (y + 1) ==0) {
ans++;
x = x / (y + 1);
if(x < y) swap(x, y);
}
cout << "Case #" << ca << ": ";
cout << ans << endl;
}
return 0;
}