习题5-15 Fibonacci的复仇(Revenge of Fibonacci,ACM/ICPC Shanghai 2011,UVa12333)

原题链接: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;
}
发布了104 篇原创文章 · 获赞 97 · 访问量 4515

猜你喜欢

转载自blog.csdn.net/TK_wang_/article/details/104810688