南昌邀请赛网络赛 C. Angry FFF Party(python大数 + 矩阵快速幂计算斐波那契数列)

题目链接:

Angry FFF Party

 

题意:

定义斐波那契数列:F[1]=1,F[2]=1,F[n]=F[n-1]+F[n-2] (n>=3) 。给定一个 w ,w<=10^{100000} ,要求在 F[F[x]] 中找任意个数,其和等于 w ,输出其 x 。若有多组解,输出字典序最小的。若不存在,输出 -1 。

 

思路:

设 ff[x] = F[F[x]]。斐波那契数列增长速度接近 2^{n} ,因此 ff[x] 增速接近 2^{2^{n}} 。用 py 打表可知,在 [1,10^{100000}] 的范围中,有29个ff[x](即 ff[30] > 10^{100000} )。

如何打表:

由于10^{100000}范围内斐波那契数列有 >10^{5} 项,不能将其存入一个数组中(大数是字符串,空间会爆)。因此可以用矩阵快速幂计算斐波那契数列[F[n],F[n-1]]=[1,1]*(\begin{bmatrix} 1 &1 \\ 1 &0 \end{bmatrix})^{n-2},其中 n>=2 。然后直接对 ff[x] 打表即可。

由于 ff[x] 中各项跨度很大,经计算可以发现只有 <=5 的数有多种组合方式。而且 ff[x] 只有29项,因此我们直接从 ff[x] 最后一项开始遍历,若 w>ff[i],w-=ff[i],并把该 ff[i] 记入答案,遍历到5即可停止,最后5项特判即可。

 

tips:py range区间左闭右开 。

 

Code:(py 2.7)

def Mul(a,b):
    c = [[0,0],[0,0]]
    c[0][0]=a[0][0]*b[0][0]+a[0][1]*b[1][0]
    c[0][1]=a[0][0]*b[0][1]+a[0][1]*b[1][1]
    c[1][0]=a[1][0]*b[0][0]+a[1][1]*b[1][0]
    c[1][1]=a[1][0]*b[0][1]+a[1][1]*b[1][1]
    return c

def fastm(a,num):
    res=[[1,0],[0,1]]
    while num>0:
        if num%2==1:
            res = Mul(res,a)
        num=num/2
        a=Mul(a,a)
    x=res[0][0]+res[1][0]
    return x

f=[[1,1],[1,0]]
ff=[0,1,1,1,2,5]
for i in range(6,30):
    x = fastm(f,i-2)
    ff.append(fastm(f,x-2))

t = int(input())
while t>0:
    t=t-1
    ans=[]
    w = int(input())
    for i in range(29,0,-1):
        if i<=5:
            break
        if w>=ff[i]:
            w=w-ff[i]
            ans.append(i)
    if w>5:
        ans.append(5)
        w=w-5
        if w>5:
            print(-1)
            continue
    if w==5:
        ans=ans+[4,3,2,1]
    elif w==4:
        ans=ans+[4,2,1]
    elif w==3:
        ans=ans+[3,2,1]
    elif w==2:
        ans=ans+[2,1]
    elif w==1:
        ans.append(1)
    for i in ans[:0:-1]:
        print(i),
    print ans[0]

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值