首页 > 代码库 > [hdu 3830] checker

[hdu 3830] checker

题意

  在一维空间内玩三个跳棋.

  给定三个跳棋初始点的坐标 $a, b, c$ , 问它们能不能跳到结束点 $x, y, z$ .

  如果能, 还要求出最少跳多少次.

  $- {10} ^ 9 \le a, b, c, x, y, z \le {10} ^ 9$ .

 

分析

 

实现

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <algorithm>
using namespace std;

#define F(i, a, b) for (register int i = (a); i <= (b); i++)
#define P(i, a, b) for (register int i = (a); i >= (b); i--)

#define LL long long

inline LL rd(void) {
    LL f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == -) f = -1;
    LL x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-0; return x*f;
}

inline void Order(LL &x, LL &y, LL &z) {
    static LL tmp[3]; tmp[0] = x, tmp[1] = y, tmp[2] = z;
    sort(tmp, tmp+3), x = tmp[0], y = tmp[1], z = tmp[2];
}

inline void Root(LL &x, LL &y, LL &z, LL &d) {
    while (y-x != z-y)
        if (y-x < z-y) {
            LL D = y-x;
            LL c = ((z-1)-y) / D;
            d += c;
            x += c * D;
            y += c * D;
        }
        else {
            LL D = z-y;
            LL c = (y-(x+1)) / D;
            d += c;
            y -= c * D;
            z -= c * D;
        }
}
inline void Go(LL &x, LL &y, LL &z, LL d) {
    while (d > 0)
        if (y-x < z-y) {
            LL D = y-x;
            LL c = min(((z-1)-y) / D, d);
            d -= c;
            x += c * D;
            y += c * D;
        }
        else {
            LL D = z-y;
            LL c = min((y-(x+1)) / D, d);
            d -= c;
            y -= c * D;
            z -= c * D;
        }
}

int main(void) {
    #ifndef ONLINE_JUDGE
        freopen("hdu3830.in", "r", stdin);
        freopen("hdu3830.out", "w", stdout);
    #endif
    
    LL a, b, c, x, y, z;
    while (~scanf("%I64d", &a)) {
        b = rd(), c = rd(), x = rd(), y = rd(), z = rd();
        Order(a, b, c), Order(x, y, z);
        
        LL ra = a, rb = b, rc = c, rs = 0; Root(ra, rb, rc, rs);
        LL rx = x, ry = y, rz = z, rw = 0; Root(rx, ry, rz, rw);
        if (ra != rx || rb != ry || rc != rz) { puts("NO"); continue; }
        
        LL res = 0;
        if (rs < rw) swap(a, x), swap(b, y), swap(c, z), swap(rs, rw);
        Go(a, b, c, rs-rw), res += (rs-rw), rs = rw;
        if (a == x && b == y && c == z) { puts("YES"); printf("%I64d\n", res); continue; }
        P(i, 60, 0) if ((1LL << i) <= rs) {
            Go(ra = a, rb = b, rc = c, 1LL << i);
            Go(rx = x, ry = y, rz = z, 1LL << i);
            if (ra != rx || rb != ry || rc != rz) {
                rs -= (1LL << i), rw -= (1LL << i);
                a = ra, b = rb, c = rc, x = rx, y = ry, z = rz;
                res += 2 * (1LL << i);
            }
        }
        puts("YES"), printf("%I64d\n", res+2);
    }
    
    return 0;
}

 

[hdu 3830] checker