原题链接:https://vjudge.net/problem/UVA-12333
分类:STL综合
备注:大整数类,缩小范围
前言:UVA这提交系统也太不给力了,崩了好久。因为我还没学字典树啊,而且也没到书上字典树的部分,所以我想尽量不用字典树。我的代码借鉴了一篇博客:https://www.cnblogs.com/jionkitten/p/12259389.html。主要思想是只存前8位数,这个题就是预处理特别慢,搜索是很快的,尝试存其它位数说不定也可以。
启发:本题让我知道没必要一定构造数据结构才能快速处理,适度缩小数据的保存范围也是很有效的。还有,这次吸取到的教训是代码一定得检查仔细了,用于调试的代码分散在多处忘了去掉,总是WA,谨记一定要仔细!
代码如下:
#include<iostream>
#include<cstdio>
#include<vector>
#include<string>
#include<set>
#include<map>
#include<algorithm>
using namespace std;
const int maxn = 100000 + 5;
map<string, set<int> >id;
struct BigInteger {
static const int BASE = 100000000;
static const int WIDTH = 8;
vector<int> s;
BigInteger operator = (const string& str) {
s.clear();
int x, len = (str.length() - 1) / WIDTH + 1;
for (int i = 0; i < len; i++) {
int end = str.length() - i * WIDTH;
int start = max(0, end - WIDTH);
sscanf(str.substr(start, end - start).c_str(), "%d", &x);
s.push_back(x);
}
return *this;
}
void sum(const BigInteger& x1, const BigInteger& x2, int xb) {
s.clear();
for (int i = 0, g = 0;; i++) {
if (g == 0 && i >= x1.s.size() && i >= x2.s.size())break;
int x = g;
if (i < x1.s.size())x += x1.s[i];
if (i < x2.s.size())x += x2.s[i];
s.push_back(x % BASE);
g = x / BASE;
}
string now, now2;
if (s.size() == 1) {//恰好该数小于等于8位
now = to_string(s[0]);
while (now.length() > 0) {
id[now].insert(xb);
now = now.substr(0, now.length() - 1);
}
return;
}
int len = 1, k = 10, k2 = 1, x = s.back();
while (x / k) { len++; k = (k << 1) + (k << 3); }//求出最前的数有几位,要求凑齐8位
for (int i = 0; i < 8 - len; i++)k2 = (k2 << 1) + (k2 << 3);
x = s[s.size() - 2] / k + s.back() * k2;
now = to_string(x);
while (now.length() > 0) {
id[now].insert(xb);
now = now.substr(0, now.length() - 1);
}
}
bool find(string str) {
int x = s.back(), len = 1, len2 = 0, base = 10;
while (x / base) { len++; base = (base << 1) + (base << 3); }
if (len + (s.size() - 1) * 8 < str.length())return false;
len2 = str.length(); int pos = s.size() - 1;
base /= 10;
for (int i = 0; i < len2; pos--, len = 8, base = 10000000)
while (len && i < len2) {
if (s[pos] / base % 10 != str[i] - '0')return false;
base /= 10;
i++; len--;
}
return true;
}
}f[maxn];
int main(void) {
int n, kase = 0;
string s = "1";
f[0] = f[1] = s;
id[s].insert(0);
for (int i = 2; i < 100000; i++)
f[i].sum(f[i - 1], f[i - 2], i);
scanf("%d", &n);
while (n--) {
cin >> s;
printf("Case #%d: ", ++kase);
int len = s.length();
if (len <= 8) {
if (id.count(s))printf("%d\n", *id[s].begin());
else printf("-1\n");
}
else {
int flag = 0;
string tmp = s.substr(0, 8);
for (set<int>::iterator it = id[tmp].begin(); it != id[tmp].end(); ++it) {
if (f[*it].find(s)) {
printf("%d\n", *it);
flag = 1;
break;
}
}
if (!flag)printf("-1\n");
}
}
return 0;
}