Description
小白和小蓝在一起上数学课,下课后老师留了一道作业,求下面这个数列的通项公式:
小白作为一个数学爱好者,很快就计算出了这个数列的通项公式。于是,小白告诉小蓝自己已经做出来了,但为了防止小蓝抄作业,小白并不想把公式公布出来。于是小白为了向小蓝证明自己的确做出来了此题以达到其炫耀的目的,想出了一个绝妙的方法:即让小蓝说一个正整数N,小白则说出的值,如果当N很大时小白仍能很快的说出正确答案,这就说明小白的确得到了公式。但这个方法有一个很大的漏洞:小蓝自己不会做,没法验证小白的答案是否正确。作为小蓝的好友,你能帮帮小蓝吗?
Input
输入文件第一行有且只有一个正整数T,表示测试数据的组数。
第2~T+1行,每行一个非负整数N。
Output
输出文件共包含T行。
第i行应包含一个不含多余前缀0的数,它的值应等于An(n为输入数据中第i+1行被读入的整数)
【样例输入】
Sample Input
3
1
3
10
1
3
10
Sample Output
1
2
3
2
3
HINT
T<=20,N<=10^100
Source
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
二叉树+高精度~
刚开始用十进制写的,结果T了,时限2s跑了2.9s……然后学黄学长的改成了10000进制……太神了……
输出的时候用%04d,可以补全前导0。
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define rad 10000
int t,c[105],len;
char s[105];
struct node{
int a[105],len;
node(){
len=1;a[1]=0;
}
void clear()
{
memset(a,0,sizeof(a));len=1;
}
}n,p,q;
node operator + (node u,node v)
{
if(u.len<v.len) swap(u,v);
int w=v.len;
for(int i=1;i<=w;i++) u.a[i]+=v.a[i];
for(int i=1;i<=w;i++)
if(u.a[i]>=rad)
{
if(i==u.len)
{
u.a[i+1]=0;u.len++;
}
u.a[i+1]+=u.a[i]/rad;
u.a[i]%=rad;
w=max(w,i+1);
}
return u;
}
node operator + (node u,int v)
{
node b;
b.len=1;b.a[1]=v;
return u+b;
}
node operator / (node u,int v)
{
for(int i=u.len;i;i--)
{
u.a[i-1]+=(u.a[i]%v)*rad;u.a[i]/=v;
}
while(!u.a[u.len] && u.len) u.len--;u.a[0]=0;
return u;
}
void findd(node u)
{
if(u.len==1 && u.a[1]==1)
{
p=u;q.clear();return;
}
findd((u+1)/2);
if(u.a[1]&1) p=q+p;
else q=p+q;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%s",s);
len=strlen(s);
for(int i=1;i<=len;i++) c[i]=s[len-i]-'0';
for(int i=1;i<=4;i++) c[i+len]=0;
n.len=(len-1)/4+1;
for(int i=1;i<=n.len;i++)
{
n.a[i]=0;
for(int j=1;j<=4;j++) n.a[i]=n.a[i]*10+c[(i-1)*4+5-j];
}
findd(n);
printf("%d",p.a[p.len]);
for(int i=p.len-1;i;i--) printf("%04d",p.a[i]);printf("\n");
}
return 0;
}
原来的程序,T掉了。
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int t;
char s[101];
struct node{
int a[1001],len;
}n,c[2];
node cheng(node u,int v)
{
for(int i=1;i<=u.len;i++) u.a[i]*=v;
for(int i=1;i<=u.len;i++)
{
u.a[i+1]+=u.a[i]/10;
u.a[i]%=10;
}
if(u.a[u.len]) u.len++;
return u;
}
node chu(node u,int v)
{
for(int i=u.len;i;i--)
{
u.a[i-1]+=(u.a[i]%v)*10;
u.a[i]/=v;
}
u.a[0]=0;
while(!u.a[u.len]) u.len--;
return u;
}
node jia(node u,node v)
{
if(u.len<v.len) swap(u,v);
for(int i=1;i<=u.len;i++)
{
u.a[i]+=v.a[i];
u.a[i+1]+=u.a[i]/10;
u.a[i]%=10;
}
if(u.a[u.len+1]) u.len++;
return u;
}
node jiac(node u,int v)
{
u.a[1]+=v;
for(int i=1;i<=u.len;i++)
if(u.a[i]<10) break;
else
{
u.a[i+1]++;u.a[i]%=10;
}
if(u.a[u.len+1]) u.len++;
return u;
}
bool operator == (node u,node v)
{
if(u.len!=v.len) return 0;
for(int i=1;i<=u.len;i++) if(u.a[i]!=v.a[i]) return 0;
return 1;
}
node cal(node u)
{
if(u==c[0]) return c[0];
if(u==c[1]) return c[1];
if(u==c[2]) return c[2];
if(u.a[1]%2)
{
node l=chu(u,2),r=jiac(l,1);
return jia(cal(l),cal(r));
}
return cal(chu(u,2));
}
int main()
{
scanf("%d",&t);
c[0].len=c[1].len=c[2].len=1;c[0].a[1]=0;c[1].a[1]=c[2].a[1]=1;
while(t--)
{
scanf("%s",s);
n.len=strlen(s);int now=0;
for(int i=n.len-1;i>=0;i--) n.a[n.len-i]=s[i]-'0';
node ans=cal(n);
while(!ans.a[ans.len]) ans.len--;
for(int i=ans.len;i;i--) printf("%d",ans.a[i]);printf("\n");
}
return 0;
}