zoukankan      html  css  js  c++  java
  • 【BZOJ2656】[Zjoi2012]数列(sequence) 高精度

    【BZOJ2656】[Zjoi2012]数列(sequence)

    Description

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

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

    Input

          输入文件第一行有且只有一个正整数T,表示测试数据的组数。

         第2~T+1行,每行一个非负整数N。

    Output

          输出文件共包含T行。

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

    【样例输入】

    Sample Input

    3
    1
    3
    10

    Sample Output

    1
    2
    3

    HINT

    T<=20,N<=10^100

    题解:一开始以为真的要推什么通项公式。。。

    我们反过来推,发现第一次变成1-2个数,以后就一直是2个相邻的数。。。所以只需要实现高精度+1,-1,>>1,a+b,在逆着推的时候维护一下系数即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    int T;
    
    struct Cbig
    {
    	int a[110],len;
    	int & operator [] (int b) {return a[b];}
    	Cbig() {memset(a,0,sizeof(a)),len=1;}
    	Cbig div2()
    	{
    		Cbig b;
    		b.len=len;
    		for(int i=len;i>=1;i--)	b[i]+=a[i],b[i-1]=(b[i]&1)*10,b[i]>>=1;
    		while(b.len>1&&!b[b.len])	b.len--;
    		return b;
    	}
    	Cbig dec()
    	{
    		Cbig b;
    		memcpy(b.a,a,sizeof(a)),b.len=len;
    		b[1]--;
    		for(int i=1;i<=len;i++)	if(b[i]<0)	b[i]+=10,b[i+1]--;
    		while(b.len>1&&!b[b.len])	b.len--;
    		return b;
    	}
    	Cbig inc()
    	{
    		Cbig b;
    		memcpy(b.a,a,sizeof(a)),b.len=len;
    		b[1]++;
    		for(int i=1;i<=len;i++)	b[i+1]+=b[i]/10,b[i]%=10;
    		while(b[b.len+1])	b.len++;
    		return b;
    	}
    	Cbig operator + (Cbig b) const
    	{
    		Cbig c;
    		c.len=max(len,b.len);
    		for(int i=1;i<=c.len;i++)	c[i]+=a[i]+b[i],c[i+1]+=c[i]/10,c[i]%=10;
    		while(c[c.len+1])	c.len++;
    		return c;
    	}
    	void print()
    	{
    		for(int i=len;i>=1;i--)	printf("%d",a[i]);
    		printf("
    ");
    		return ;
    	}
    }A,B,X,Y;
    int n;
    char str[110];
    void work()
    {
    	scanf("%s",str),n=strlen(str);
    	int i;
    	A=B=X=Y=Cbig();
    	A.len=n;
    	for(i=0;i<n;i++)	A[n-i]=str[i]-'0';
    	if(A.len==1&&A[1]==0)	{printf("0
    ");	return ;}
    	if(A.len==1&&A[1]==1)	{printf("1
    ");	return ;}
    	while(!(A[1]&1))	A=A.div2();
    	if(A.len==1&&A[1]==1)	{printf("1
    ");	return ;}
    	B=A.inc(),A=A.dec(),A=A.div2(),B=B.div2(),X[1]=Y[1]=1;
    	while(1)
    	{
    		if(A[1]&1)	Y=Y+X,A=A.dec(),A=A.div2(),B=B.div2();
    		else	X=X+Y,B=B.inc(),A=A.div2(),B=B.div2();
    		if(A.len==1&&A[1]==0)	break;
    	}
    	Y.print();
    }
    int main()
    {
    	scanf("%d",&T);
    	while(T--)	work();
    	return 0;
    }//3 1 3 10
  • 相关阅读:
    centos shell脚本编程1 正则 shell脚本结构 read命令 date命令的用法 shell中的逻辑判断 if 判断文件、目录属性 shell数组简单用法 $( ) 和${ } 和$(( )) 与 sh -n sh -x sh -v 第三十五节课
    基于HTML5 WebGL实现 json工控风机叶轮旋转
    基于HTML5的WebGL实现的2D3D迷宫小游戏
    基于HTML5和WebGL的碰撞测试
    基于HTML5和WebGL的3D网络拓扑结构图
    基于 HTML5 WebGL 的 3D 网络拓扑图
    基于HTML5 Canvas 实现弹出框
    基于HTML5 Canvas实现用户交互
    基于HTML5快速搭建TP-LINK电信拓扑设备面板
    HTML5 技术在风电、光伏等新能源领域的应用
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7787721.html
Copyright © 2011-2022 走看看