Problem Description
There is a computer, which has two memory cells (let us denote these cells by the letters a and b). Each cell (variable) stores some integer at any time. The computer can execute only two instructions a+=b and b+=a. The first instruction increases the value of the variable a by the value stored in the variable b. The second one, respectively, increases the value of b by the value a. A program for this computer consists of a sequence (possible empty) of such instructions. The instructions are executed in the appropriate order. Your task is to determine whether the given value S can be obtained in some cell after executing some program.
Input
The input file contains several test cases, each of them as described below.
The input contains three integers: the initial value of the variable a, the initial value of the variableb and the required value S (0 ≤ a, b, S ≤ 10^18).
Output
For each test case, write to the output ‘YES’ if the required value can be obtained as a result of some program execution, or ‘NO’ otherwise on a line by itself.
Sample Input
1 2 3
3 4 5
3 4 17
Sample Output
YES
NO
YES
解题思路
判断 ax+by=s ……(1)是否存在非负整数解, 且满足 gcd(x,y)=1 。
根据扩展欧几里得算法知,存在整数(x, y) 满足
ax+by=gcd(a,b)
;
因此我们可以先根据 【gcd(a, b) 能否整除 s】 来判断 是否存在 整数解。
引理:设 a,b,c 为任意整数。若方程 ax+by=c 的一组整数解为 (x0,y0) ,则它的任意整数解都可以写成 (x0+k∗b′,y0−k∗a′) , 其中 a′=a/gcd(a,b),b′=b/gcd(a,b)
令
d=gcd(a,b);
(1)式 转化为
a′x+b′y=s′
……(2)
其中
a′=a/d,b′=b/d,s′=s/d;
然后求出一组
x,y
满足
a′x+b′y=1
……(3);
这个算出的
x,y
要乘上
s′
才是和 (2)式等价 即
x∗=s′,y∗=s′;
然后根据
x
找到最小非负整数解
最后枚举所有
参考代码
#include <stdio.h>
typedef long long ll;
//扩展欧几里得算法 : 求解满足ax+by=1的一组解,且d = gcd(a, b);
void exgcd(ll a, ll b, ll& d, ll& x, ll& y) {
if (!b) {
d = a; x = 1; y = 0;
} else {
exgcd(b, a % b, d, y, x);
y -= x * (a / b);
}
}
ll gcd(ll a, ll b){return b ? gcd(b, a % b) : a;}
ll a, b, s, d, x, y;
void work() {
// 特判有0的情况
if (a == 0) {
if (b == 0) printf("%s\n", s ? "NO" : "YES");
else printf("%s\n", s % b ? "NO" : "YES");
return ;
} else if (b == 0) {
printf("%s\n", s % a ? "NO" : "YES");
return ;
}
exgcd(a, b, d, x, y);
if (s % d) {
puts("NO");
return ;
}
a /= d; b /= d; s /= d;
x *= s % b; x %= b;
while (x < 0) x += b;
y = (s - a * x) / b;
while (y >= 0) {
if (gcd(x, y) == 1) {
puts("YES");
return ;
}
x += b; y -= a;
}
puts("NO");
}
int main() {
while (~scanf("%lld %lld %lld", &a, &b, &s)) work();
return 0;
}