UVALive6428 A+B【扩展欧几里得算法+GCD】
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;
}
 
                     
                    
                 
                    
                 
                
            
         
 
         浙公网安备 33010602011771号
浙公网安备 33010602011771号