X-Magic Pair gcd,剪枝(1600)

在这里插入图片描述
题意 :

  • 给一个数对a,b和一个数x,每次操作可以选择使a或者b变成 ∣ a − b ∣ |a-b| ab(即变成它们的差值),问在若干次(0)操作后,是否能使得a或者b等于x

方案一 :

  • 如果一开始就有一个数等于x,直接true;如果一开始就两个数都小于x,直接false,因为a和b都是正整数,每次操作都会使其中一个变小
  • 对于一对(a,b),假设a>=b,考虑对a操作,此时如果通过若干次操作,使得要求被满足,那么我们可以记为 a − p ∗ b = x a-p*b=x apb=x,要使得一个正整数p存在,需要满足 a > = x , 且 x a>=x,且x a>=x,x% b = a b=a b=a% b b b 也就是 ( a − x ) (a-x) (ax)% b = 0 b=0 b=0,当方程组被满足时,说明有解
  • 如果当前无解,我们可以对余下的数继续进行操作,这就相当于对 ( b , a (b,a (b,a% b ) b) b)这一对数继续进行求解,这一部分我们可以通过递归来实现
  • 过程中还有两个剪枝特判,如果小的那个数为0,直接false;如果满足上述方程组,直接true
#include <iostream>

using namespace std;
using ll = long long;

ll a, b, x;

bool check(ll a, ll b)
{
    if (b == 0) return false;
    if (a >= x && a % b == x % b) return true;
    return check(b, a % b);
}

void solve()
{
    cin >> a >> b >> x;
    if (a == x || b == x) cout << "Yes" << endl;
    else if (a < x && b < x) cout << "No" << endl;
    else
    {
        if (a < b) swap(a, b);
        cout << (check(a, b) ? "Yes" : "No") << endl;
    }
}

int main()
{
    cin.tie(nullptr) -> sync_with_stdio(false);
    
    int _;
    cin >> _;
    
    while (_ -- )
        solve();
}

方案二 :

  • 这和 更相减损术 很像(每次迭代其中一个数变成了差值),因此想到了gcd
  • 裸gcd不一定能过,因此尽可能的剪枝
  • 讲一下其中的一个剪枝。我们假设a>=b,且每次对a迭代,那么每次a都减少一个b,因此,只要a与x的差值是若干个b,那么直接剪枝判断true
#include <iostream>

using namespace std;
using ll = long long;

ll a, b, x;

bool gcd(ll a, ll b)
{
    if (a < b) swap(a, b);		// 假设a是大的那个
    if (a == x || b == x) return true;		// == x
    if (a == 0 || b == 0) return false;		// x>=1
    if (a < x && b < x) return false;		// 不可能变成x了
    if (a >= x && (a - x) % b == 0) return true;	// 大的那个和x的差值是小的那个的倍数
    return gcd(a % b, b);
}

void solve()
{
    cin >> a >> b >> x;

    if (a == x || b == x) cout << "YES" << endl;
    else if (a < x && b < x) cout << "NO" << endl;
    else cout << (gcd(a, b) ? "YES" : "NO") << endl;
}

int main()
{
    cin.tie(nullptr) -> sync_with_stdio(false);

    int _;
    cin >> _;

    while (_ -- )
        solve();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值