HDU6726 Transformation [思维题, 二分]

TransformationTransformation

题目描述见链接 .


\color{red}{正解部分}

考虑从 (c,d)(c, d) 逆推回 (a,b)(a, b) ,

首先看 (c,d)(c, d) 是由什么转移过来的, 经过简单推导知 (c+d2,d),(c,c+d2)(\frac{c+d}{2}, d),(c,\frac{c+d}{2}) 可以转移到 (c,d)(c, d),

若把 (c,d)(c, d) 看成区间, 可以发现 从 (c,d)(c,d)(a,b)(a, b) 是一个 类二分 的过程 .

于是就可以通过逆推 二分 出步骤, 得到答案了 .


\color{red}{实现部分}

注意判无解的情况,

  • 注意当 a,ba, bc,dc, d 之间的大小关系不同时, 需要判无解 .
  • c+d2\frac{c+d}{2} 必须是整数 .
  • 逆推的前提为 ac,bda \geq c, b \le d .
  • 二分时若发现 amida \le midb>midb > mid 或者 a<mida < midbmidb \geq mid的情况, 说明无解 .
#include<bits/stdc++.h>
#define reg register
typedef long long ll;

ll read(){
        char c;
        ll s = 0, flag = 1;
        while((c=getchar()) && !isdigit(c))
                if(c == '-'){ flag = -1, c = getchar(); break ; }
        while(isdigit(c)) s = s*10 + c-'0', c = getchar();
        return s * flag;
}

int T;
int top;

bool stk[100];

void Work(){
        ll a = read(), b = read(), c = read(), d = read();
        int flag = 0;
        if(c > d) std::swap(c, d), std::swap(a, b), flag = 1;
        if(a > b){ puts("No"); return ; }
        top = 0;
        while(a != c || b != d){
                if(c+d & 1ll){ puts("No"); return ; } 
                if(a < c || b > d){ puts("No"); return ; }
                ll mid = c+d >> 1;
                if(a < mid) d = mid, stk[++ top] = 1;
                else c = mid, stk[++ top] = 0;
        }
        puts("Yes");
        while(top) putchar((stk[top --]^flag)?'A':'B');
        puts("");
}

int main(){
        scanf("%d", &T);
        while(T --) Work();
        return 0;
}
posted @ 2019-09-24 23:21  XXX_Zbr  阅读(147)  评论(0编辑  收藏  举报