PKU 3982-序列

問題概要

A(n)=A(n-1)+A(n-2)+A(n-3)(n>=3)とする.
A(0),A(1),A(2)が与えられるので,A(99)の値を求めよ

考え方

多倍長で計算するだけ

実装(C++)

#include <vector>
#include <iostream>
#include <string>
#include <deque>
#include <algorithm>
#include <map>
using namespace std;
const int BI_MAX=10000;
struct BigInteger{
        deque<short> val;
        int flags;
        BigInteger(int n=0){
                flags=0;
                if(n)flags=n/abs(n);
                while(n)val.push_back(n%BI_MAX),n/=BI_MAX;
        }
        void clear_leading_zero(){while(val.back()==0)val.pop_back();}
        string to_string(){
                if(val.size()==0)return "0";
                char res[val.size()*4+5];char *r;r=res+val.size()*4+4;*(r--)='\0';
                for(int i=0;i<(int)val.size();i++){
                        int t=val[i];
                        for(int j=0;j<4;j++){
                                if(t==0&&i==(int)val.size()-1)break;
                                (*r--)=t%10+'0';
                                t/=10;
                        }
                }
                return string(r+1);
        }
};
BigInteger add(const BigInteger &a,const BigInteger &b){
        BigInteger res(0);
        short va,vb,k=0;
        for(int i=0;i<max<int>(a.val.size(),b.val.size());i++){
                        if(i<(int)a.val.size())va=a.val[i];else va=0;
                        if(i<(int)b.val.size())vb=b.val[i];else vb=0;
                        va+=k;
                        k=(va+vb)>=BI_MAX;
                        res.val.push_back(va+vb-(k?BI_MAX:0));
        }
        if(k)res.val.push_back(k);
        return res;
}
BigInteger mul(const BigInteger &a,const BigInteger &b){
        int k=0,i,j;
        BigInteger res(0);
        for(int i=0;i<(int)a.val.size()+(int)b.val.size()+1;i++){
                res.val.push_back(0);
        }
        for(i=0;i<(int)a.val.size();i++){
                k=0;
                for(j=0;j<(int)b.val.size();j++){

                        k=a.val[i]*b.val[j]+k;
                        res.val[i+j]+=k%BI_MAX;
                        k/=BI_MAX;
                        if(res.val[i+j]>=BI_MAX){
                                res.val[i+j]-=BI_MAX;k++;
                        }
                }
                while(k){
                        res.val[i+j]+=k;
                        if(res.val[i+j]>=BI_MAX){res.val[i+j]-=BI_MAX;k=1;}else k=0;
                        j++;
                }
        }
        res.clear_leading_zero();
        return res;
}

BigInteger operator+(const BigInteger &a,const BigInteger &b){return add(a,b);}
BigInteger operator*(const BigInteger &a,const BigInteger &b){return mul(a,b);}
int a[3];
map<int,BigInteger> dp;
BigInteger solve(int x){
	if(x<=2)return a[x];
	if(dp.find(x)!=dp.end())return dp[x];
	dp[x]=solve(x-1)+solve(x-2)+solve(x-3);
	return dp[x];
}

int main() {
	for(;cin>>a[0]>>a[1]>>a[2];){
		dp.clear();
		cout<<solve(99).to_string()<<endl;
	}
	return 0;
}