题目描述:斐波那切数列f(n+2)=f(n+1)+f(n)
给一个输入:2<=x<=2^32,给出所有可能的斐波那切数列中的位置。(描述不太准确,看测试用例)
测试用例:输入
3
输出:
3 2
4 1
意思是x的位置在3的数列有两种,在4的数列有1种(输出的位置小于3的不算(即不能以x作为数列的前两项))
他们分别是 1 1 2 3;1 2 3;2 1 3; (然后按位置较小的顺序输出)
直接暴力循环所有可能性只有10%的正确率,提示时间超时(所以我也不确定我的代码是否正确,贴上来,可以讨论下)
#include<iostream>
#include<map>
#include<vector>
using namespace std;
int main()
{
long long x;
cin >> x;
map<long long, int>mp;
for (long long i = 1; i < x; i++)
{
for (long long j = 1;i+j<=x; j++)
{
long long pre1 = i;
long long pre2 = j;
long long sum = pre1+pre2;
long long num = 2;
while (sum < x)
{
num++;
pre1 = pre2;
pre2 = sum;
sum = pre1 + pre2;
}
if (sum == x)
{
num++;
if (num >= 3)
{
mp[num]++;
}
}
}
}
map<long long, int>::iterator it=mp.begin();
for (;it!=mp.end();it++)
{
cout << it->first << " " << it->second << endl;
}
system("pause");
return 0;
}
去牛大神客上搜了搜回答,给大神跪了。
直接复制下的解释:
作者:莫得感情的拒信收割机
链接:https://www.nowcoder.com/discuss/250292
来源:牛客网
大概思想是,如果给的数是x,假设前一个数为y,那么倒数第三个数是x-y,倒数第四个数是2y-x,然后保证每个数>0,可以得到m的区间。3个数m介于1到x之间,4个数的话y介于1/2x到x之间,5个数的话y介于1/2x到2/3x之间,注意都是开区间。会发现那个分数的分子分母是斐波拉契数列,然后更新就好了。如果y取不到了,就停止循环.(侵权删)
想了很久,解释一下吧。
我以数组res存放每次计算的结果。
假设只有三个数即,x-y, y, x.
则可以推出 ,所以y的所有可能取值为,也就是res[3]=x-1;
再假设有四个数:2y-x , x-y, y , x
则可以推出,所以 (因为是开区间所以减1)
再假设有五个数:2x-3y ,2y-x , x-y, y , x
则可以推出,所以
然后大神说分子分母的系数是斐波那切数列序列
有点蒙,又计算了一个
再假设有六个数:5y-3x,2x-3y ,2y-x , x-y, y , x
则可以推出,所以
然后整理一下系数的关系
x-1;
以下是我总结的比较笨的规律啊
第一个首先更新迭代时有一项是保持不变的,先是第一项,然后第二项(当更新奇数位置时第一项更新,更新偶数位置相反)
第二个大神给出的:
首先初始化res[3]=x-1;
然后第一个等式的x前的系数可以看做
更新下一组参数时保持第一项不变,为,(此时数列为1 1)第二项的分子更新为f(n+1),即1,而分母更新为f(n+2)=f(n)+f(n+1) 即2 ,然后更新数列(1 1 2),
再更新下一组参数时,保持第二项不变,更新第一项,分子为分f(n+1)=2;分母为f(n)+f(n+1)=3,更新数列(1 1 2 3)
再更新下一组参数时,保持第一项不变,更新第二项,分子为分f(n+1)=3;分母为f(n)+f(n+1)=5,更新数列(1 1 2 3 5)
那么推测res[7]的表达式:
保持第二项不变,更新第一项,分子为分f(n+1)=5;分母为f(n)+f(n+1)=8,更新数列(1 1 2 3 5 8)
即表达式应该为:,
用数学推导一下:七个数的话数列应该为5x-8y, 5y-3x,2x-3y ,2y-x , x-y, y , x,结果正是,往下就不推了:
以下是代码:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
long long x;
cin >> x;
vector<long long>res(10000);
vector<long long>fn(10000);
res[3] = x - 1;//结果输出,
//fn[3] = 1;//可以用来保存中间计算的结果
int num = x - 1;
int pre1 = 1;//存放分子分母状态的序列
int pre2 = 1;
int i = 3;
while (num > 0)
{
i++;
if (i % 2 == 0)
{
//int c1 = (pre1 / pre2)*x;
//int c2 = (pre2 / (pre1 + pre2))*x;测试用的,千万别写成这种形式
num = (pre1*x / pre2) - (pre2 *x/(pre1 + pre2))-1;
pre1 = pre2;
pre2 = pre1 + pre2;
if (num > 0)
{
res[i] = num;
}
else
{
break;
}
}
else
{
num = (pre2 *x/(pre1 + pre2)) - (pre1*x / pre2) - 1;
pre1 = pre2;
pre2 = pre1 + pre2;
if (num > 0)
{
res[i] = num;
}
else
{
break;
}
}
}
i = 3;
while (res[i] > 0)
{
cout << i << " " << res[i] << endl;
i++;
}
system("pause");
return 0;
}
因为没有测试平台,不知道对不对,欢迎指正错误。