Provincial election ban Day1
Naughty Fairies
Although my approach T, but it should make high-precision pan back (more on T N-up)
Probably about the same algorithm and teachers? (Why so unlike my dp)
First convert the number to binary
That can not be directly greedy?
We found that if the target is a prefix, then just need to * 2 and +1/0 alternately on the line
Is that right?
hack: 1111 11111
Because \ (--1 \) operation, found that greed can not guarantee the accuracy, GG the
But it is also inspired us to become the target prefix and prefix \ (+ 1 \) is equally important
This allows \ (DP \) a (is not it amazing)
\ (dp [i] [j ] \) represents the current to the second process \ (I \) bits is a prefix or prefix \ (1 + \) )
Transfer:
\[ if ~(b[i]=0)~ dp[i][0]=min(dp[i-1][0]+1,dp[i-1][1]+2),dp[i][1]=min(dp[i-1][0]+2,dp[i-1][1]+2)\\ else ~dp[i][0]=min(dp[i-1][0]+2,dp[i-1][1]+2), dp[i][1]=min(dp[i-1][0]+2,dp[i-1][1]+1)\\ \]
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define cls(a) memset(a, 0, sizeof(a))
#define rise(i, a, b) for (int i = a; i <= b; i++)
#define fall(i, a, b) for (int i = a; i >= b; i--)
const int base = 1e9;
char a[600];
bool ined, flag;
int cnt, cntt, ep;
void init() {
ined = false;
cnt = 0;
while (true) {
a[cnt] = getchar();
if (a[cnt] >= '0' && a[cnt] <= '9') {
ined = true;
cnt++;
} else if (ined)
break;
}
a[cnt] = '\0';
cnt--;
}
struct point {
int num[60], len;
point() { clear(); }
void clear() {
len = 1;
cls(num);
}
void out(int x) {
printf("%d", num[len]);
fall(i, len - 1, 1) printf("%09d", num[i]);
if (x)
putchar('\n');
else
putchar(' ');
}
void in() {
init();
cntt = 0;
ep = 1;
clear();
fall(i, cnt, 0) {
if (cntt == 9) {
cntt = 0;
len++;
ep = 1;
}
cntt++;
num[len] += (int)(a[i] - '0') * ep;
ep *= 10;
}
while (len > 1 && num[len] == 0) len--;
}
void inc() {
num[1]++;
rise(i, 1, len) {
if (num[i] >= base) {
num[i + 1]++;
num[i] -= base;
} else
break;
}
if (num[len + 1] == 1)
len++;
}
void dec(int x) {
num[1] -= x;
rise(i, 1, len) {
if (num[i] < 0) {
num[i + 1]--;
num[i] += base;
} else
break;
}
if (num[len] == 0)
len--;
}
void divid() {
fall(i, len, 1) {
num[i - 1] += (num[i] & 1) * base;
num[i] >>= 1;
}
if (num[len] == 0)
len--;
}
point &operator=(const point &);
point operator-(const point &) const;
point operator+(const point &) const;
point(const int);
bool operator>(const point &p) const;
bool operator<(const point &p) const;
bool operator==(const point &p) const;
} n, m, one, zero, two, now[3], tmp[5], nv[3], tv[5], ans;
point &point ::operator=(const point &p) {
clear();
len = p.len;
rise(i, 1, len) num[i] = p.num[i];
return *this;
}
point point ::operator+(const point &p) const {
point ret = *this;
int l = max(ret.len, p.len);
rise(i, 1, l) {
ret.num[i] += p.num[i];
if (ret.num[i] >= base) {
ret.num[i + 1]++;
ret.num[i] -= base;
}
}
if (ret.num[l + 1] > 0)
l++;
ret.len = l;
return ret;
}
point point ::operator-(const point &p) const {
point ret = *this;
if (ret > p) {
rise(i, 1, ret.len) {
ret.num[i] -= p.num[i];
if (ret.num[i] < 0) {
ret.num[i] += base;
ret.num[i + 1]--;
}
}
while (ret.len > 1)
if (ret.num[ret.len] == 0)
ret.len--;
else
break;
return ret;
}
if (ret == p)
return zero;
if (ret < p) {
point tmp = ret;
ret = p;
rise(i, 1, ret.len) {
ret.num[i] -= tmp.num[i];
if (ret.num[i] < 0) {
ret.num[i] += base;
ret.num[i + 1]--;
}
}
while (ret.len > 1)
if (ret.num[ret.len] == 0)
ret.len--;
else
break;
return ret;
}
}
point::point(const int b) {
clear();
num[1] = b;
}
bool point::operator==(const point &p) const {
if (len != p.len)
return false;
fall(i, len, 1) if (num[i] != p.num[i]) return false;
return true;
}
bool point::operator>(const point &p) const {
if (len > p.len)
return true;
if (len < p.len)
return false;
fall(i, len, 1) {
if (num[i] > p.num[i])
return true;
if (num[i] < p.num[i])
return false;
}
return false;
}
bool point::operator<(const point &p) const {
if (len < p.len)
return true;
if (len > p.len)
return false;
fall(i, len, 1) {
if (num[i] < p.num[i])
return true;
if (num[i] > p.num[i])
return false;
}
return false;
}
int main() {
one = point(1);
zero = point(0);
two = point(2);
int cnt = 1;
while (true) {
m.in();
n.in();
if (n == zero && m == zero)
break;
if (n > m || n == m) {
(n - m).out(1);
continue;
}
now[1] = m;
ans = m - n;
cnt = 1;
cntt = 0;
while (cnt) {
rise(i, 1, cnt) {
if (ans > now[i] - n + nv[i])
ans = now[i] - n + nv[i];
if (now[i].num[1] % 2 == 0) {
flag = 0;
rise(j, 1, cntt) if (now[i] == tmp[j]) {
if (nv[i] < tv[j])
tv[j] = nv[i];
flag = true;
}
if (!flag) {
tmp[++cntt] = now[i];
tv[cntt] = nv[i];
}
} else {
nv[i].inc();
flag = false;
now[i].inc();
rise(j, 1, cntt) if (now[i] == tmp[j]) {
if (nv[i] < tv[j])
tv[j] = nv[i];
flag = true;
}
if (!flag) {
tmp[++cntt] = now[i];
tv[cntt] = nv[i];
}
if (now[i] > two) {
flag = false;
now[i].dec(2);
rise(j, 1, cntt) if (now[i] == tmp[j]) {
if (nv[i] < tv[j])
tv[j] = nv[i];
flag = true;
}
if (!flag) {
tmp[++cntt] = now[i];
tv[cntt] = nv[i];
}
}
}
now[i].clear();
nv[i].clear();
}
cnt = 0;
rise(i, 1, cntt) {
if ((tmp[i].len > 1 || tmp[i].num[1] > 2) && tmp[i] > n) {
tmp[i].divid();
nv[++cnt] = tv[i] + one;
now[cnt] = tmp[i];
}
tmp[i].clear();
tv[i].clear();
}
cntt = 0;
}
ans.out(1);
}
return 0;
}