DTOJ 1184:数列(sequence)

DTOJ 1184:数列(sequence)

【题目描述】

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

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

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

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

【样例输入】
3
1
3
10
【样例输出】
1
2
3
【分析】
    对于每个数,需要考虑它是奇数还是偶数。若是偶数,也可以化为奇数。而最终所有的数都会化到0和1。不妨设原数为K1*A[1]+k2*A[0],则它必定是由某一个数转化而来。不难发现,k1*A[2i]+k2*A[2i+1]=(k1+k2)*A[i]+k2*A[i+1],另一种情况也类似。所以按照这个式子不断化简即可。
【代码】
#include<bits/stdc++.h>
using namespace std;
class INT
{
    public:
        int l,nm[120];
        inline void read ( void )
        {
            char ch[120];scanf(" %s",ch+1);
            l=strlen(ch+1);
            for ( int i=1;i<=l;i++ ) nm[i]=ch[l-i+1]-48;
        }
        inline void write ( void )
        {
            for ( int i=l;i;i-- ) putchar(nm[i]+48);
            putchar('\n');
        }
        inline bool is_one ( void ) { return (l==1)&&(nm[1]==1); }
        inline bool is_odd ( void ) { return nm[1]&1; }
        INT operator + ( const INT &x ) const
        {
            INT ret;ret.nm[1]=0;ret.l=max(l,x.l);
            for ( int i=1;i<=ret.l;i++ )
            {
                ret.nm[i]+=(i<=l?nm[i]:0)+(i<=x.l?x.nm[i]:0);
                ret.nm[i+1]=ret.nm[i]/10;ret.nm[i]%=10;
            }
            if ( ret.nm[ret.l+1] ) ret.l++;
            return ret;
        }
        INT operator / ( const int &x ) const
        {
            INT ret;ret.l=l;ret.nm[l]=0;
            for ( int i=l;i;i-- )
            {
                ret.nm[i]+=nm[i];
                if ( i>1 ) ret.nm[i-1]=ret.nm[i]%x*10;
                ret.nm[i]/=x;
            }
            while ( !ret.nm[ret.l] ) ret.l--;
            return ret;
        }
}x,y,a,b;
inline void sequence_main ( void )
{
    x.read();a.l=b.l=a.nm[1]=b.nm[1]=1;
    while ( !x.is_odd() ) x=x/2;
    if ( x.is_one() ) { a.write();return; }
    y=x/2;
    while ( !y.is_one() )
        if ( y.is_odd() ) y=y/2,b=a+b;
        else y=y/2,a=a+b;
    x=a+b;x.write();
}
int main(){int T;scanf("%d",&T);while(T--)sequence_main();return 0;}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值