HDU 5802
题意:
三种操作使 p 变为 q;
1)休息,什么也不做 ;
2) 让 p 加 1 ;
3)让 p 减 1 ,如果上一次操作减去了 x ,那么这一次会减去 2 * x ;
如果上一次的操作是 休息 或者 加 1 ,那么只能让 p 减 1;
求最少的操作数 。
解题:
自己先开始模拟没模出来...
看题解写的,我的理解是酱紫的
p 可以减的数是 1 2 4 8 ... 如果连续减 x 次的话也就是 (2^x)-1 ;
先让 p 减到当前最靠近的 q 的位置 ,此时 p 是 p<=q 的;
如果恰好 p == q ,那么就可以返回结果了;
如果没有,那就选择是减到 p <= q 再加回来,还是休息再继续从 1 开始减;
因为休息和加 1 都可以让 p 从 1 开始减,所以如果有 加的操作
那么之前停的次数就可以不算了。
#include<bits/stdc++.h> #define ll long long using namespace std; ll dfs(ll s, ll e, ll ste, ll sto) { if(s == e) return ste; ll x = 0 ; while(s - (1<<x) + 1 > e) x++; if( s - (1<<x) + 1 == e) return ste + x; ll up = e - max((ll)0, s - (1<<x) + 1 ) ; // ll ano = x + max((ll)0, up-sto); return min(ano+ste, dfs( (s - (1<<(x-1)) + 1 ), e, ste+x, sto+1 ) ); } int main() { int t; ll p,q; scanf("%d",&t); while(t--) { scanf("%I64d%I64d",&p,&q); if( p <= q ) { printf("%I64d ",q-p); continue; } ll ans = dfs(p,q,0,0); printf("%I64d ",ans); } return 0; }