高精度整数+STL。看到题的想法其实是高精度整数+Trie,然而Trie并没写过(也写不来),何况时间足足有10s,也没必要用Trie,于是使用了字符串加法+unordered_set。为了加快查找,不同长度的前缀分别单独开unordered_set存放。方便起见,所有数字我都是反着存+用的。加法没必要保存整段数字,前50位就够用了(反正后面进位小到可以忽略)。另外,说好了smaller than 100000真的多一点也不行,之前没仔细看结果一直WA。
写这题刚开始没想到只用前50位。之后写完字符串版本后试了一下算到100000,感觉有超时的可能,于是就改用大整数板子了,没想到大整数只用了1570ms。后来想通了就简单改成了字符串+前50位,立刻510ms。优化空间其实还很大,代码写的也很烂。
#include <iostream> #include <cstdlib> #include <vector> #include <algorithm> #include <unordered_set> #include <unordered_map> #include <set> using namespace std; #define _for(i,j,k) for (int i=(j); i<=(k); i++) string rev_add(string& a, string& b) { string r; int i = 0, carry = 0, sum = 0; while (i < a.size() || i < b.size()) { sum = carry; if (i < a.size()) sum += (int) (a[i] - '0'); if (i < b.size()) sum += (int) (b[i] - '0'); r.push_back(sum % 10 + '0'); carry = sum / 10; i++; } if (carry > 0) r.push_back(carry + '0'); if (r.size() > 50) { a = a.substr(1, a.size() - 1); b = b.substr(1, b.size() - 1); return r.substr(r.size() - 50, r.size()); } return r; } unordered_set<string> quizCache[41]; unordered_map<string, vector<int>> quizCase; int main() { string num; int n, *output, min_length = 0, cur = 1, end, numLen; cin >> n; output = (int*) malloc(n * sizeof(int)); _for(i,0,n-1) { cin >> num; if (num == "1") { output[i] = 0; continue; } output[i] = -1; reverse(num.begin(),num.end()); quizCache[num.size()].insert(num); if (quizCase.count(num) == 0) quizCase[num] = vector<int>(); quizCase[num].push_back(i); } while (++min_length <= 40 && quizCache[min_length].size() == 0); string fn_2 = "1", fn_1 = "1", fn, sub; while (min_length <= 40 && cur < 100000 - 1) { fn = rev_add(fn_2, fn_1); fn_2 = fn_1; fn_1 = fn; cur++; if (fn.size() < min_length) continue; _for(length,min_length,min((int) fn.size(), 40)) { if (quizCache[length].size() == 0) continue; sub = fn.substr(fn.size()-length, fn.size()); if (quizCache[length].count(sub) > 0) { quizCache[length].erase(sub); for (int ind: quizCase[sub]) output[ind] = cur; if (quizCache[length].size() == 0) { min_length = 0; while (++min_length <= 40 && quizCache[min_length].size() == 0); } } } } _for(i,0,n-1) cout << "Case #" << i+1 << ": " << output[i] << endl; return 0; }