地方選挙解禁1日目
いたずらな妖精
私のアプローチTが、それは戻って高精度なパンを作る必要があります(詳細は上のT Nアップ)
おそらく同じアルゴリズムや教師はどうですか?(なぜ私のDPとは異なります)
まずバイナリに数値を変換
それは直接貪欲することはできませんか?
私たちは、ターゲットが接頭辞である場合は、ちょうど2 *する必要があることを発見し+1/0交互の行に
その権利はありますか?
ハック:1111 11111
ので\(--1 \)操作、貪欲は、GG正確性を保証することはできませんことを発見
しかし、また、ターゲットのプレフィックスとプレフィックスになるために私たちに触発された(+ 1 \)は\同様に重要です
これは、ことができます\(DP \) (それは驚くべきではありませんが)
\(DP [I] [jが 】\) 第二のプロセスへの電流を表し\を(私は\)ビット接頭辞または接頭辞である\(1 + \) )
転送:
\ [〜(B [I] = 0)〜DP [I] [0] =分(DP [I-1] [0] + 1、DP [I-1] [1] +2)、DP [ならI] [1] =分(DP [I-1] [0] + 2、DP [I-1] [1] +2)\\他〜DP [i]が[0] =分(DP [1- 1] [0] + 2、DP [I-1] [1] +2)、DP [I] [1] =分(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;
}