【ZJOI2012】bzoj2656 数列

来源:互联网 发布:打印机的端口怎么看 编辑:程序博客网 时间:2024/04/29 08:56

Description

小白和小蓝在一起上数学课,下课后老师留了一道作业,求下面这个数列的通项公式:

小白作为一个数学爱好者,很快就计算出了这个数列的通项公式。于是,小白告诉小蓝自己已经做出来了,但为了防止小蓝抄作业,小白并不想把公式公布出来。于是小白为了向小蓝证明自己的确做出来了此题以达到其炫耀的目的,想出了一个绝妙的方法:即让小蓝说一个正整数N,小白则说出
的值,如果当N很大时小白仍能很快的说出正确答案,这就说明小白的确得到了公式。但这个方法有一个很大的漏洞:小蓝自己不会做,没法验证小白的答案是否正确。作为小蓝的好友,你能帮帮小蓝吗?

Input

  输入文件第一行有且只有一个正整数T,表示测试数据的组数。 第2~T+1行,每行一个非负整数N。

Output

  输出文件共包含T行。

第i行应包含一个不含多余前缀0的数,它的值应等于An(n为输入数据中第i+1行被读入的整数)

计算

xai+yai+1={xai/2+(x+y)ai/2+1(x+y)ai/2+yai/2+1ii

发现和原问题形式一样,迭代求解。复杂度O(logn)

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define LL long longconst int mod=10000;char s[210];struct big{    int a[210],l;    void rd()    {        scanf("%s",s+1);        l=(strlen(s+1)-1)/4+1;        for (int i=1,p=strlen(s+1);i<=l;i++)        {            a[i]=s[p]-'0';            if (p-1>0) a[i]+=10*(s[p-1]-'0');            if (p-2>0) a[i]+=100*(s[p-2]-'0');            if (p-3>0) a[i]+=1000*(s[p-3]-'0');            p-=4;        }    }    big operator + (const big &bb) const    {        big ret;        ret.a[1]=0;        ret.l=max(l,bb.l);        for (int i=1;i<=ret.l;i++)        {            ret.a[i]+=(i<=l?a[i]:0)+(i<=bb.l?bb.a[i]:0);            ret.a[i+1]=ret.a[i]/mod;            ret.a[i]%=mod;        }        if (ret.a[ret.l+1]) ret.l++;        return ret;    }    big operator + (const int &x) const    {        big ret;        ret.a[1]=a[1]+x;        ret.l=l;        for (int i=1;i<=ret.l;i++)        {            ret.a[i+1]+=ret.a[i]/mod;            ret.a[i]%=mod;        }        while (ret.a[ret.l+1]) ret.l++;        return ret;    }    big operator * (const int &x) const    {        big ret;        ret.a[1]=0;        for (int i=1;i<=l;i++)        {            ret.a[i]+=a[i]*x;            ret.a[i+1]=ret.a[i]/mod;            ret.a[i]%=mod;        }        ret.l=l;        while (ret.a[ret.l+1])        {            ret.a[ret.l+1]=ret.a[ret.l]/mod;            ret.a[ret.l]%=mod;            ret.l++;        }        return ret;    }    bool odd()    {        return a[1]%2;    }    big operator / (const int &x) const    {        big ret;        ret.l=l;        ret.a[l]=0;        for (int i=l;i;i--)        {            ret.a[i]+=a[i];            if (i>1) ret.a[i-1]=ret.a[i]%x*mod;            ret.a[i]/=x;        }        while (!ret.a[ret.l]) ret.l--;        return ret;    }    bool isone()    {        return l==1&&a[1]==1;    }    bool iszero()    {        return l<=1&&a[1]==0;    }    void out()    {        printf("%d",a[l]);        for (int i=l-1;i;i--)        {            if (a[i]<1000) putchar('0');            if (a[i]<100) putchar('0');            if (a[i]<10) putchar('0');            printf("%d",a[i]);        }    }}x,y,a,b;int main(){    int T;    scanf("%d",&T);    while (T--)    {        x.rd();        while (!x.odd()) x=x/2;        if (x.isone())        {            printf("1\n");            continue;        }        y=x/2;        a.l=b.l=a.a[1]=b.a[1]=1;        while (!y.isone())        {            if (y.odd())            {                y=y/2;                b=a+b;            }            else            {                y=y/2;                a=a+b;            }        }        (a+b).out();        putchar('\n');    }}
0 0
原创粉丝点击