[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;
}
时间: 2024-10-11 11:54:48

[hdu 3830] checker的相关文章

HDU 3830 Checkers

题意: 有三个棋子  可以隔一个棋子跳  不能隔两个跳  问状态u到状态v最少跳几步 思路: 对于一个状态三个棋子的位置可以设为 x y z  (小到大) 只有当y-x=z-y的时候  跳的方法为两种  即  y跳过x  或  y跳过z 在上式等式不成立时  短的一边可以跳许多次  直到大小关系改变 那么这样就形成了二叉树的结构  我们将y向左右跳的状态分别作为原状态的儿子  将两边其中一个向中间跳的状态作为原状态的父亲 那么这时u和v的可达性就变成了  他们是不是同一个根  于是我们可以从u和

学习 LCA&amp;&amp;RMQ

参考:点击打开链接 点击打开链接      点击打开链接(一些总结) 点击打开链接(不错的模板) 题目:点击打开链接 花了4天时间做完了这个专题,LCA的问题用处还是很大,同时能体会RMQ的ST算法中dp的味道.基本方法就是ST,LCA转RMQ,LCA的Tarjan,LCA倍增(这个可存储边权) 这个专题后面四道题都非常好,推荐大家做做. 细节: 1. ST方法2^i 包含自己,因此其真实只包含到i+2^k-1的范围. 2. Tarjan一般都很快,但不适合修改类型的问题,关于权值长度之类的,S

LCA&amp;&amp;RMQ问题

参考:点击打开链接 点击打开链接      点击打开链接(一些总结) 点击打开链接(不错的模板) 题目:点击打开链接 花了4天时间做完了这个专题,LCA的问题用处还是很大,同时能体会RMQ的ST算法中dp的味道.基本方法就是ST,LCA转RMQ,LCA的Tarjan,LCA倍增(这个可存储边权) 这个专题后面四道题都非常好,推荐大家做做. 细节: 1. ST方法2^i 包含自己,因此其真实只包含到i+2^k-1的范围. 2. Tarjan一般都很快,但不适合修改类型的问题,关于权值长度之类的,S

图论 500题——主要为hdu/poj/zoj

转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并查集======================================[HDU]1213   How Many Tables   基础并查集★1272   小希的迷宫   基础并查集★1325&&poj1308  Is It A Tree?   基础并查集★1856   More i

[tarjan] hdu 3836 Equivalent Sets

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3836 Equivalent Sets Time Limit: 12000/4000 MS (Java/Others)    Memory Limit: 104857/104857 K (Java/Others) Total Submission(s): 2890    Accepted Submission(s): 1006 Problem Description To prove two set

hdu图论题目分类

=============================以下是最小生成树+并查集====================================== [HDU] 1213 How Many Tables 基础并查集★ 1272 小希的迷宫 基础并查集★ 1325&&poj1308 Is It A Tree? 基础并查集★ 1856 More is better 基础并查集★ 1102 Constructing Roads 基础最小生成树★ 1232 畅通工程 基础并查集★ 123

HDU 5059 Help him (模拟)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5059 Problem Description As you know, when you want to hack someone's program, you must submit your test data. However sometimes you will submit invalid data, so we need a data checker to check your data

HDU 6203 ping ping ping [LCA,贪心,DFS序,BIT(树状数组)]

题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=6203] 题意 :给出一棵树,如果(a,b)路径上有坏点,那么(a,b)之间不联通,给出一些不联通的点对,然后判断最少有多少个坏点. 题解 :求每个点对的LCA,然后根据LCA的深度排序.从LCA最深的点对开始,如果a或者b点已经有点被标记了,那么continue,否者标记(a,b)LCA的子树每个顶点加1. #include<Bits/stdc++.h> using namespace std;

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include