Ural 1286. Starship Travel (扩展欧几里得)

题意:给你p、q,初始状态(x1, y1),终点状态(x2, y2),每次操作可以是 (+p, +q), (+p, -q) , (-p, +q), (-p, -q), (+q, +p), (+q, -p), (-q, +p), (-q, -p),问初始状态能不能到终点状态。


思路:对于初始状态到终止状态变化了 (x2-x1, y2-y1),设为变化了(A, B) ,得方程 px1 + qy1 = A, px2 + qy2 = B,很容易得知满足x1, y2奇偶情况相同和y1,x2奇偶情况相同就可以。然后只需要算出x,y的相对奇偶情况,比较下就可以了。

坑的是。。。明明FAQ里写64位用long long,为何我改成__int64才过。。。坑了好久啊

code:

#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
using namespace std;
typedef __int64 ll;

ll exgcd(ll a, ll b, ll &x, ll &y) {
    if(!b) {
        x = 1; y = 0;
        return a;
    }
    ll ret = exgcd(b, a%b, y, x);
    y -= a/b*x;
    return ret;
}

ll ABS(ll x) {
    return x > 0 ? x : -x;
}

int v1[111], v2[111];

bool solve(ll a, ll b, ll N, int f[111]) {
    if(a == 0) {
        if(b == 0) {
            if(!N) {
                f[11] = f[22] = f[12] = f[21] = 1;
                return true;
            }
            return false;
        }
        else {
            if(N%b == 0) {
                if((N/b) & 1)   f[11] = f[21] = 1;
                else    f[12] = f[22] = 1;
                return true;
            }
            return false;
        }
    }
    else if(b == 0) {
        if(N%a == 0) {
            if((N/a) & 1)   f[12] = f[11] = 1;
            else    f[22] = f[21] = 1;
            return true;
        }
        return false;
    }
    ll x, y, d = exgcd(a, b, x, y);
    if(!N) {
        a /= d; b /= d;
        int w = (b&1) ? 1 : 2, e = (a&1) ? 1 : 2;
        f[w*10+e] = 1;
        f[22] = 1;
        return true;
    }
    if(N % d)   return false;
    x *= N/d; y *= N/d;
    int w = (x&1) ? 1 : 2, e = (y&1) ? 1 : 2;
    f[w*10+e] = 1;
    x += b/d; y -= a/d;
    w = (x&1) ? 1 : 2, e = (y&1) ? 1 : 2;
    f[w*10+e] = 1;
    return true;
}

int main() {
    ll p, q, x1, x2, y1, y2;
    scanf("%I64d%I64d%I64d%I64d%I64d%I64d", &p, &q, &x1, &y1, &x2, &y2);
    if(p < 0)   p = -p;
    if(q < 0)   q = -q;
    ll A = x2-x1, B = y2-y1;
    if(A < 0)   A = -A;
    if(B < 0)   B = -B;
    if(!solve(p, q, A, v1) || !solve(p, q, B, v2))    puts("NO");
    else {
        //printf("v1 11 = %d 12 = %d 21 = %d 22 = %d\n", v1[11], v1[12], v1[21], v1[22]);
        //printf("v2 11 = %d 12 = %d 21 = %d 22 = %d\n", v2[11], v2[12], v2[21], v2[22]);
        if((v1[11] && v2[11]) || (v1[12] && v2[21]) || (v1[21] && v2[12]) || (v1[22] && v2[22]))  puts("YES");
        else    puts("NO");
    }
    return 0;
}

      
      
     
     
    
    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值