博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ2656: [Zjoi2012]数列(sequence)
阅读量:5275 次
发布时间:2019-06-14

本文共 3466 字,大约阅读时间需要 11 分钟。

Description

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

A(0)=0

A(1)=1

A(2i)=A(i) (对于任意 i>0)

A(2i+1)=A(i)+A(i+1) (对于任意 i>0)

   小白作为一个数学爱好者,很快就计算出了这个数列的通项公式。

于是,小白告诉小蓝自己已经做出来了,但为了防止小蓝抄作业,小白并不想把公式公布出来。

于是小白为了向小蓝证明自己的确做出来了此题以达到其炫耀的目的,想出了一个绝妙的方法:

即让小蓝说一个正整数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


题解Here!

 

先不管那个$n<=10^{100}$。。。

首先考虑一个问题:设$u\times A(i)+v\times A(i+1)=x\times A(\frac{i}{2})+y\times A(\frac{i}{2}+1)$,$i,u,v$已知,$x,y$未知。

求在$i$分别为奇数和偶数时$x,y$的一组正整数解。

我们可以想到:

1. $i$为偶数时,$i+1$为奇数。

此时有:$$u\times A(i)+v\times A(i+1)=u\times A(\frac{i}{2})+v\times (A(\frac{i}{2})+A(\frac{i}{2}+1))=(u+v)\times A(\frac{i}{2})+v\times A(\frac{i}{2}+1)$$

2. $i$为奇数时,$i+1$为偶数。

此时有:$$u\times A(i)+v\times A(i+1)=u\times (A(\frac{i}{2})+A(\frac{i}{2}+1))+v\times A(\frac{i}{2}+1)=u\times A(\frac{i}{2})+(u+v)\times A(\frac{i}{2}+1)$$

所以得出:

1. $i$为偶数时,$x=u+v,y=v$

2. $i$为奇数时,$x=u,y=u+v$

再回到原来的问题。

由于$10^{100}$,暴力递推肯定不行。

我们就考虑像倍增一样一倍一倍地递推。

首先不断地把$n$除以$2$,直到$n$不是$2$的倍数为止。

然后可以看出:$$Ans=A(\frac{n}{2})+A(\frac{n}{2}+1)$$。

此时,根据前面得出的结论,不断地把$n$缩小一倍,最后可以得到这样的式子:$$u\times A(0)+v\times A(1)$$。

而由于$A(0)=0,A(1)=1$,于是结果就是$v$。

高精实现即可。

但是这个高精好难写啊。。。

我表示再也不想写高精了。。。

附代码:

#include
#include
#include
#include
#define MAXN 110using namespace std;struct Bignum{ int len,val[MAXN]; void clean(){ len=0; memset(val,0,sizeof(val)); } void read(){ char c=0; while(c<'0'||c>'9')c=getchar(); while(c>='0'&&c<='9'){val[++len]=c-'0';c=getchar();} for(int i=1;i<=len/2;i++)swap(val[i],val[len-i+1]); } void write(){ for(int i=len;i>=1;i--)printf("%d",val[i]); printf("\n"); } friend Bignum operator +(Bignum x,int k){ int c=0; for(int i=1;i<=x.len&&k;i++){ x.val[i]+=k%10+c; k/=10; c=x.val[i]/10; x.val[i]%=10; } if(c)x.val[++x.len]+=c; while(k){ x.val[++x.len]=k%10; k/=10; } return x; } friend Bignum operator +(Bignum x,Bignum y){ int c=0,l=max(x.len,y.len); for(int i=1;i<=l;i++){ x.val[i]+=y.val[i]+c; c=x.val[i]/10; x.val[i]%=10; } x.len=l; if(c)x.val[++x.len]+=c; return x; } friend Bignum operator >>(Bignum x,const int k){ for(int i=x.len;i>=1;i--){ if(x.val[i]&1)x.val[i-1]+=10; x.val[i]>>=1; } while(x.len>1&&!x.val[x.len])x.len--; return x; }}n;inline int read(){ int date=0,w=1;char c=0; while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();} while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();} return date*w;}Bignum solve(Bignum num){ if(num.len==1&&(num.val[1]==0||num.val[1]==1))return num; while((num.val[1]&1)==0)num=num>>1; Bignum l=num>>1,r=l+1,u,v; u.clean();v.clean();u.len=v.len=u.val[1]=v.val[1]=1; while(l.len>1||l.val[1]){ if(l.val[1]&1)v=u+v; else u=u+v; l=l>>1;r=l+1; } return v;}int main(){ int t=read(); while(t--){ n.clean();n.read(); n=solve(n); n.write(); } return 0;}

 

转载于:https://www.cnblogs.com/Yangrui-Blog/p/9490641.html

你可能感兴趣的文章
kill新号专题
查看>>
MVC学习系列——Model验证扩展
查看>>
mysqladmin 修改和 初始化密码
查看>>
字符串
查看>>
vue2.x directive - 限制input只能输入正整数
查看>>
实现MyLinkedList类深入理解LinkedList
查看>>
自定义返回模型
查看>>
C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本 - 客户端多网络支持
查看>>
HDU 4122
查看>>
Suite3.4.7和Keil u3自带fx2.h、fx2regs.h文件的异同
查看>>
打飞机游戏【来源于Crossin的编程教室 http://chuansong.me/account/crossincode 】
查看>>
[LeetCode] Merge Intervals
查看>>
【翻译自mos文章】当点击完 finishbutton后,dbca 或者dbua hang住
查看>>
Linux编程简介——gcc
查看>>
2019年春季学期第四周作业
查看>>
MVC4.0 利用IActionFilter实现简单的后台操作日志功能
查看>>
rotate the clock
查看>>
bugku 变量
查看>>
Python 环境傻瓜式搭建 :Anaconda概述
查看>>
数据库01 /Mysql初识以及基本命令操作
查看>>