Regionals 2013 >> Europe - Southeastern
问题链接:UVALive6428 A+B。
问题分析:
可以看作是解方程ax+by=s的问题。
先用扩展欧几里德算法进行计算,求得ax+by=gcd(a,b)=d。若s%d!=0,则无解。
若有解,再进行迭代计算求得最小非负解。
另外一个关键的地方在于需要考虑a,b和s为0的情形。
AC的C++语言程序如下:
/* UVALive6428 A+B */
#include <iostream>
using namespace std;
typedef long long LL;
// 递推法实现扩展欧几里德算法
LL exgcd(LL a, LL b, LL *x, LL *y)
{
LL x0=1, y0=0, x1=0, y1=1;
LL r, q;
*x=0;
*y=1;
r = a % b;
q = (a - r) / b;
while(r)
{
*x = x0 - q * x1;
*y = y0 - q * y1;
x0 = x1;
y0 = y1;
x1 = *x;
y1 = *y;
a = b;
b = r;
r = a % b;
q = (a - r) / b;
}
return b;
}
/* 递归法:欧几里得算法,计算最大公约数 */
LL gcd(LL m, LL n)
{
return (m == 0) ? n : gcd(n%m, m);
}
int main()
{
LL a, b, s, x, y, d;
bool ans;
while(cin >> a >> b >> s) {
if(a == 0 && b == 0) {
ans = (s == 0);
} else if(a == 0) {
ans = (s % b == 0);
} else if(b == 0) {
ans = (s % a == 0);
} else {
d = exgcd(a, b, &x, &y);
if(s % d != 0)
ans = false;
else {
LL x0 = b / d;
LL y0 = a / d;
x= ((s / d % x0) * (x % x0) % x0 + x0)%x0;
y= (s - x * a) / b;
ans = false;
while(y > 0) {
if(gcd(x, y) == 1) {
ans = true;
break;
} else {
x += x0;
y -= y0;
}
}
}
}
cout << (ans ? "YES" : "NO") << endl;
}
return 0;
}