定义数列 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
。 可以发现a
和b
的系数都是斐波那契数列。当start-1
位置上a
的系数为i
,b
的的系数为j
时,start
位置上a
的系数为j
, b
的的系数为i+j
。
确定完位置start
上,a
的系数为i
,b
的系数为j
后,我们只用计算有多少种a
,b
的组合使得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
不互质。记它们的最大公约数为
i
和
j
有公约数
i
和
j
不互质,与条件"当第
start
个位置上的数为
i
,第
start+1
个位置上的数为
j
,命题成立"矛盾,所以第
start+1
个位置上的数
j
和第
start+2
位置的数
i+j
互质。