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;
}