题目大意:定义个一序列,f[i] = f[i / 2] (i % 2 == 0);f[i] = f[i / 2] + f[i / 2 + 1] (i % 2 == 1);求这个数列的第m项(m <= 10 ^ 100)
思路:数据范围高精度没跑了。记得之前做过这个题的弱化版,似乎是没有高精度的记忆化搜索,这个题就是加个高精度。
CODE:
#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 210
#define MO 10
using namespace std;
#define max(a,b) ((a) > (b) ? (a):(b))
class BigInt{
private:
int num[MAX],len;
public:
BigInt(int _ = 0) {
memset(num,0,sizeof(num));
num[len = 1] = _;
}
void Read() {
static char s[MAX];
scanf("%s",s);
len = strlen(s);
for(int i = 1; i <= len; ++i)
num[i] = s[len - i] - '0';
}
friend ostream &operator <<(ostream &os,const BigInt &a);
bool operator <(const BigInt &a)const {
if(len == a.len) {
for(int i = len; i; --i)
if(num[i] != a.num[i])
return num[i] < a.num[i];
}
return len < a.len;
}
bool Odd()const {
return num[1]&1;
}
BigInt operator +(const BigInt &a)const {
BigInt re;
re.len = max(len,a.len);
int temp = 0;
for(int i = 1; i <= re.len; ++i) {
re.num[i] = temp + num[i] + a.num[i];
temp = re.num[i] / MO;
re.num[i] %= MO;
}
if(temp) re.num[++re.len] = temp;
return re;
}
BigInt operator /(int c)const {
BigInt re;
re.len = len;
int temp = 0;
for(int i = len; i; --i) {
re.num[i] = (num[i] + temp) / 2;
temp = (num[i] + temp) % 2 * MO;
}
while(!re.num[re.len]) --re.len;
return re;
}
}temp;
ostream &operator <<(ostream &os,const BigInt &a)
{
os << a.num[a.len];
for(int i = a.len - 1; i; --i)
os << a.num[i];
return os;
}
map<BigInt,BigInt> G;
int T;
BigInt &MemorialSearch(const BigInt &a)
{
if(G.find(a) != G.end()) return G[a];
if(a.Odd())
G[a] = MemorialSearch(a / 2) + MemorialSearch(a / 2 + 1);
else G[a] = MemorialSearch(a / 2);
return G[a];
}
int main()
{
G[0] = BigInt(0);
G[1] = BigInt(1);
for(cin >> T; T--;) {
temp.Read();
cout << MemorialSearch(temp) << endl;
}
return 0;
}