[BZOJ2656][codevs1207][Zjoi2012]数列(sequence)
试题描述
小白和小蓝在一起上数学课,下课后老师留了一道作业,求下面这个数列的通项公式:
小白作为一个数学爱好者,很快就计算出了这个数列的通项公式。于是,小白告诉小蓝自己已经做出来了,但为了防止小蓝抄作业,小白并不想把公式公布出来。于是小白为了向小蓝证明自己的确做出来了此题以达到其炫耀的目的,想出了一个绝妙的方法:即让小蓝说一个正整数N,小白则说出 的值,如果当N很大时小白仍能很快的说出正确答案,这就说明小白的确得到了公式。但这个方法有一个很大的漏洞:小蓝自己不会做,没法验证小白的答案是否正确。作为小蓝的好友,你能帮帮小蓝吗?
输入
输入文件第一行有且只有一个正整数T,表示测试数据的组数。
第2~T+1行,每行一个非负整数N。
输出
输出文件共包含T行。
第i行应包含一个不含多余前缀0的数,它的值应等于An(n为输入数据中第i+1行被读入的整数)
输入示例
3 1 3 10
输出示例
1 2 3
数据规模及约定
T<=20,N<=10^100
题解
直接暴力记忆化搜索,用 map 保存状态。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <algorithm> #include <map> using namespace std; int read() { int x = 0, f = 1; char c = getchar(); while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); } while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); } return x * f; } struct LL { int len, A[105]; LL() {} LL operator = (const int& t) { if(!t){ A[1] = 0; len = 1; return *this; } len = 0; int T = t; while(T) A[++len] = T % 10, T /= 10; return *this; } LL operator + (const int& t) const { LL ans; ans = *this; ans.A[1] += t; for(int i = 2; i <= ans.len; i++) ans.A[i] += ans.A[i-1] / 10, ans.A[i-1] %= 10; while(ans.A[ans.len] > 9) ans.A[ans.len+1] = ans.A[ans.len] / 10, ans.A[ans.len] %= 10, ans.len++; return ans; } LL operator + (const LL& t) const { LL ans; ans = *this; ans.len = max(ans.len, t.len); for(int i = 1; i <= ans.len; i++) ans.A[i] += t.A[i]; for(int i = 2; i <= ans.len; i++) ans.A[i] += ans.A[i-1] / 10, ans.A[i-1] %= 10; while(ans.A[ans.len] > 9) ans.A[ans.len+1] = ans.A[ans.len] / 10, ans.A[ans.len] %= 10, ans.len++; return ans; } LL operator / (const int& t) const { LL ans; ans.len = 1; int f = 0; for(int i = len; i; i--) { f = f * 10 + A[i]; if(f >= t) ans.len = max(ans.len, i); ans.A[i] = f / t; f %= t; } return ans; } bool operator < (const LL& t) const { if(len != t.len) return len < t.len; for(int i = len; i; i--) if(A[i] != t.A[i]) return A[i] < t.A[i]; return 0; } void print() { for(int i = len; i; i--) putchar(A[i] + '0'); return ; } void read() { char c = getchar(); while(!isdigit(c)) c = getchar(); len = 0; while(isdigit(c)) { A[++len] = c - '0'; c = getchar(); } for(int i = 1; i <= (len >> 1); i++) swap(A[i], A[len-i+1]); return ; } } ; LL n; map <LL, LL> dp; LL f(LL x) { LL zero, one; zero = 0; one = 1; if(x.len == 1 && x.A[1] == 0) return zero; if(x.len == 1 && x.A[1] == 1) return one; if(dp.count(x)) return dp[x]; if(x.A[1] & 1) return dp[x] = f(x / 2) + f(x / 2 + 1); return dp[x] = f(x / 2); } int main() { int T = read(); while(T--) { n.read(); f(n).print(); putchar(' '); } return 0; }