mirror of
https://github.com/Kiritow/OJ-Problems-Source.git
synced 2024-03-22 13:11:29 +08:00
c9791a72c9
4500-4599
138 lines
3.4 KiB
C++
138 lines
3.4 KiB
C++
#include <cstdlib>
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <algorithm>
|
|
#include <iostream>
|
|
#include <queue>
|
|
using namespace std;
|
|
typedef long long LL;
|
|
const int N = 600;
|
|
LL n;
|
|
int bit[20];
|
|
LL f[60];
|
|
LL dp[15][N];
|
|
LL POW[15];
|
|
LL seq[60];
|
|
LL suf[20];
|
|
queue<int>q;
|
|
struct Ac_Auto{
|
|
int ch[N][10];
|
|
int fail[N];
|
|
bool flag[N];
|
|
int idx, root;
|
|
int newnd() {
|
|
memset(ch[idx], 0, sizeof (ch[idx]));
|
|
flag[idx] = false, fail[idx] = 0;
|
|
return idx++;
|
|
}
|
|
void init() {
|
|
idx = 0, root = newnd();
|
|
}
|
|
void insert(LL x) {
|
|
int id = 0;
|
|
while (x) bit[id++] = x%10, x/=10;
|
|
int p = root;
|
|
for (int i = id-1; i >= 0; --i) {
|
|
if (!ch[p][bit[i]]) ch[p][bit[i]] = newnd();
|
|
p = ch[p][bit[i]];
|
|
}
|
|
flag[p] = true;
|
|
}
|
|
void build() {
|
|
for (int i = 0; i < 10; ++i) {
|
|
if (ch[root][i]) {
|
|
q.push(ch[root][i]);
|
|
}
|
|
}
|
|
while (!q.empty()) {
|
|
int u = q.front();
|
|
q.pop();
|
|
for (int i = 0; i < 10; ++i) {
|
|
int &v = ch[u][i];
|
|
int x = fail[u];
|
|
if (v) {
|
|
q.push(v);
|
|
while (x && !ch[x][i]) x = fail[x];
|
|
fail[v] = ch[x][i];
|
|
flag[v] = flag[v] || flag[fail[v]];
|
|
} else {
|
|
v = ch[x][i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void find(LL x) {
|
|
int id = 0;
|
|
while (x) bit[id++] = x%10, x/=10;
|
|
int p = root;
|
|
for (int i = id-1; i >= 0; --i) {
|
|
p = ch[p][bit[i]];
|
|
if (flag[p]) {
|
|
cout << "OMG" << endl;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
Ac_Auto ac;
|
|
LL count(int p, int sta, bool bound) {
|
|
if (p == 0) return 0;
|
|
if (!bound && ~dp[p][sta]) return dp[p][sta];
|
|
int y = bound ? bit[p] : 9;
|
|
LL sum = 0;
|
|
int tsta;
|
|
for (int i = 0; i <= y; ++i) {
|
|
tsta = ac.ch[sta][i];
|
|
if (ac.flag[tsta]) {
|
|
if (bound&&i==y) sum += suf[p-1]+1;
|
|
else sum += POW[p-1];
|
|
continue;
|
|
}
|
|
sum += ::count(p-1, tsta, bound&&i==y);
|
|
}
|
|
if (!bound) dp[p][sta] = sum;
|
|
return sum;
|
|
}
|
|
LL cal(LL x) {
|
|
int idx = 1;
|
|
while (x) suf[idx] = suf[idx-1]+x%10*POW[idx-1], bit[idx++] = x%10, x/=10;
|
|
return ::count(idx-1, ac.root, true);
|
|
}
|
|
void prepare() {
|
|
f[1] = 1, f[2] = 1;
|
|
for (int i = 3; i <= 55; ++i) {
|
|
f[i] = f[i-1] + f[i-2];
|
|
}
|
|
ac.init();
|
|
for (int i = 7; i <= 55; ++i) {
|
|
ac.insert(f[i]);
|
|
}
|
|
ac.build();
|
|
POW[0] = 1;
|
|
for (int i = 1; i < 15; ++i) POW[i] = POW[i-1] * 10;
|
|
memset(dp, 0xff, sizeof (dp));
|
|
LL tmp;
|
|
for (int i = 2; i <= 55; ++i) {
|
|
LL l = 13, r = POW[12], mid;
|
|
while (l <= r) {
|
|
mid = (l + r) >> 1;
|
|
if ((tmp=cal(mid)) < f[i]) l = mid + 1;
|
|
else if (tmp > f[i]) r = mid - 1;
|
|
else seq[i] = mid, r = mid - 1;
|
|
}
|
|
}
|
|
}
|
|
int main() {
|
|
prepare();
|
|
while (cin >> n, n != -1) {
|
|
LL ret = 1LL << 60;
|
|
for (int i = 2; i <= 55; ++i) {
|
|
LL t = seq[i] - n;
|
|
if (t < 0) t = -t;
|
|
ret = min(ret, t);
|
|
}
|
|
cout << ret << endl;
|
|
}
|
|
return 0;
|
|
}
|