题目大意:给定一个数列的通项公式,求数列的某一项
高精度+记忆化搜索没说的 其实不用记忆化搜索的但是既然写完了就写完了吧
顺便学习了一下友元函数之类的东西- -
#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
class Big_Int{
private:
int num[110],cnt;
public:
Big_Int(int _=0)
{
memset(num,0,sizeof num);
num[cnt=1]=_;
}
friend istream& operator >> (istream& _,Big_Int &x);
friend ostream& operator << (ostream& _,Big_Int &x);
bool Is_Odd()
{
return num[1]&1;
}
void operator += (const Big_Int& x)
{
int i,k=max(cnt,x.cnt);
for(i=1;i<=k;i++)
{
num[i]+=x.num[i];
num[i+1]+=num[i]/10;
num[i]%=10;
}
if(num[k+1]) k++;
cnt=k;
}
void operator >>= (int x)
{
int i;
for(i=cnt;i;i--)
{
num[i-1]+=(num[i]&1)*10;
num[i]>>=1;
}
num[0]=0;
if(!num[cnt]) --cnt;
}
bool operator < (const Big_Int &x) const
{
if(cnt != x.cnt)
return cnt < x.cnt;
int i;
for(i=cnt;i;i--)
if(num[i]!=x.num[i])
return num[i]<x.num[i];
return false;
}
};
map<Big_Int,Big_Int> f;
istream& operator >> (istream& _,Big_Int &x)
{
static char s[110];
int i;
scanf("%s",s);x.cnt=strlen(s);
for(i=1;i<=x.cnt;i++)
x.num[i]=s[x.cnt-i]-'0';
return _;
}
ostream& operator << (ostream& _,Big_Int &x)
{
int i;
printf("%d",x.num[x.cnt]);
for(i=x.cnt-1;i>0;i--)
printf("%d",x.num[i]);
return _;
}
Big_Int& Memorial_Search(Big_Int& x)
{
if(f.find(x)!=f.end())
return f[x];
Big_Int& re=f[x];
if(x.Is_Odd())
{
Big_Int s1=x;s1>>=1;
Big_Int s2=s1;s2+=Big_Int(1);
re+=Memorial_Search(s1);
re+=Memorial_Search(s2);
}
else
{
Big_Int s=x;s>>=1;
re+=Memorial_Search(s);
}
return re;
}
int main()
{
int T;
f[Big_Int(0)]=0;
f[Big_Int(1)]=1;
for(cin>>T;T;T--)
{
Big_Int n;
cin>>n;
cout<<Memorial_Search(n)<<endl;
}
return 0;
}