首页 > 代码库 > BZOJ 2656 ZJOI 2012 数列(sequence) 高精度+记忆化搜索

BZOJ 2656 ZJOI 2012 数列(sequence) 高精度+记忆化搜索

题目大意:定义个一序列,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;
}


BZOJ 2656 ZJOI 2012 数列(sequence) 高精度+记忆化搜索