用循环输出以下数列:斐波那契数列(要输出20个数字)_搜狗在线笔试题——神奇的数列

定义数列 fn+2 = fn+1 + fn,数列中任何一个元素都是正整数。从定义可以看出,不同的f1、f2会产生不同的数列。
假设给定一个数字x(2 <= x <= 232),给出这个数字出现在位置i(i >= 3, 数列下标从1开始)的数列个数。

输入描述:

数字x

输出描述:

每行为两个数字,空格分隔,第一个数字为x在数列中的位置i,第二个数字为符合条件的数列个数,即f1、f2的组合种数。若存在多行,则按照i由小到大的顺序输出

示例1
输入
3
输出
3 2 4 1
说明
以下数列包含3,分别为
1 1 2 3 5 ...
1 2 3 5 8 ...
2 1 3 4 7 ...
其中3出现在数列第三位的数列有两个,出现在第四位的数列有一个,因此输出为:
3 2
4 1

链接:https://www.nowcoder.com/questionTerminal/55975b1c45a14aafae78166617b1751f?f=discussion 来源:牛客网

思路:

首先,我们可以看x在数列的3位上出现了多少次,然后再看x在数列第4,5......位上出现了多少次。

现在问题变成了如何确定x在数列start位上出现了多少次呢?

想解决这个问题,需要找到斐波那契数列的规律,假设数列第一位上是a,第二位上是b,那么这个数列可以描述成:

a, b, a+b, a+2b, 2a+3b, 3a+5b, 5a+8b, 8a+13b .....

a 的系数为:1,0,1,1,2,3,5,8,b的系数为 :0,1,1,2,3,5,8。 可以发现ab的系数都是斐波那契数列。start-1位置上a的系数为i ,b的的系数为j时,start位置上a的系数为jb的的系数为i+j

确定完位置start上,a的系数为ib的系数为j后,我们只用计算有多少种ab的组合使得a*i+b*j=x,就可以得到x在位置start上出现了多少次。

假设有两组

都满足
, 两公式相减可以得到:
(这里假设
,那么
)。由于
在第一个位置上的数为0,第二个位置上的数为1(或者第一个位置上的数为1,第二个位置上的数为0)的斐波那契数列中的相邻两个数是互质的(后面附录有简单的证明),那么我们可以知道

即在位置start上,有

a,b的组合使得 a*i+b*j=x

最后代码如下:

import sys
import math
x = int(sys.stdin.readline().strip('n').strip())

i,j=1,1
start=3
while True:
    p=1
    while (x-i*p)%j!=0 and i*p<x:
        p+=1
    if i*p>=x:
        break
    print('{0} {1}'.format(start,math.ceil((x-i*p)*1.0/(i*j))))
    i,j=j,i+j
    start+=1

附录:
证明:在第一个位置上的数为0,第二个位置上的数为1(或者第一个位置上的数为1,第二个位置上的数为0)的斐波那契数列中相邻的两个数是互质的。

1.第一个位置上的数为0,第二个位置上的数为1时,命题成立。

2.假设当第start个位置上的数为i,第start+1个位置上的数为j,命题成立。
由于是斐波那契数列,所以第start+2位置的数为i+j

反证法:假设 第start+1个位置上的数j和第start+2位置的数i+j不互质。记它们的最大公约数为

。记
,
。那么
,又由于
,所以
ij有公约数
,即
ij不互质,与条件"当第 start个位置上的数为 i,第 start+1个位置上的数为 j,命题成立"矛盾,所以第 start+1个位置上的数 j和第 start+2位置的数 i+j互质。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值