HOJ 12899 A+B Bucharest, Romania 2013

这题题意灰常清楚不说了。

解法:可知需要用扩展欧几里德,但是并不是所有的x,y都能取得到的,找规律可得必须要互质。。为啥是互质我也不知道如何证明。。据说是因为辗转相减不是互质的无法得出一个a或者一个b,这题难度就在于会超long long,那么是在哪里会超呢?。在于算出一个x,y之后,大多数人肯定就直接乘上了s/gcd了。我也是。。想想,如果gcd是1,那么在数据大的时候必定会超,所以要取模,比如x,对b/gcd取模,然后乘上s/gcd对于b/gcd取模,这样是不会超long long的,如果x小于等于0就再加上b/gcd,y就通过s/gcd-x*a/gcd再除以b/gcd就可以算得了,这样的解就是x>0的第一个解,然后就判断gcd(x,y)是否等于1,x += b/gcd,y-=a/gcd,遍历到y<0结束,如果没有则是no,不然就是yes。

AC代码:

#include <iostream>
#include <cstdio>
#include <string.h>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;

#define ll __int64
#define NMAX 1000

void gcd(ll a, ll b, ll &d, ll &x, ll &y)
{
    if(!b){d = a; x = 1; y = 0;}
    else{gcd(b,a%b,d,y,x);y -= x*(a/b);}
}

ll ggcd(ll a,ll b)
{
    if(!b) return a;
    else ggcd(b,a%b);
}

int main()
{
    #ifdef GLQ
    freopen("input.txt","r",stdin);
//    freopen("o.txt","w",stdout);
    #endif // GLQ
    ll a,b,s,A,B;
    while(~scanf("%I64d%I64d%I64d",&a,&b,&s))
    {
        if(s < min(a,b))
        {
            printf("NO\n");
            continue;
        }
        if((a == 1 && s > b)||(b == 1 && s > a)|| a == s || b == s)
        {
            printf("YES\n");
            continue;
        }
        if(a == 0 && b == 0)
        {
            printf("NO\n");
            continue;
        }
        if(a == 0)
        {
            if(s%b == 0) printf("YES\n");
            else printf("NO\n");
            continue;
        }
        if(b == 0)
        {
            if(s%a == 0) printf("YES\n");
            else printf("NO\n");
            continue;
        }
        ll x,y,gg,w;
        gg = ggcd(a,b);
//        cout<<gg<<endl;
        if(s%gg)
        {
            printf("NO\n");
            continue;
        }

        A = a/gg;
        B = b/gg;
        gcd(A,B,w,x,y);
        x = (s/gg)%B*(x%B);
        x %= B;
        if(x <= 0) x += B;
        y = (s/gg - A*x)/B;
//        cout<<x<<" "<<y<<endl;
        int flag = 0;
        while(y > 0)
        {
//            cout<<x<<" "<<y<<endl;
            if(ggcd(x,y) == 1)
            {
                flag = 1;
                break;
            }
            x += B;
            y -= A;
        }
        if(flag) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值