第一思路比较容易想到的是暴力算法
即枚举每一个作为“起点”的元素构造一个斐波那契数列,之后对比输入的数列与枚举的数列中“区别最小”的情况,即可得到答案
#include<iostream> #include<climits> const int MAX = 1e5+10; using namespace std; int arr1[MAX]; int arr2[MAX]; int main() { int n,MAX=INT_MIN,ans=INT_MAX; cin>>n; for(int i=0;i<n;i++){ cin>>arr1[i]; if(arr1[i]>MAX)MAX=arr1[i]; } for(int i=1;i<=MAX;i++){//枚举[1,MAX]之间的数作为起点 arr2[0]=arr2[1]=i; int temp=0; for(int j=2;j<n;j++){//构造数列 arr2[j]=arr2[j-1]+arr2[j-2]; } for(int j=0;j<n;j++){//比较数列 temp+=(arr1[j]!=arr2[j]); } if(temp<ans)ans=temp; } cout<<ans<<endl; return 0; }
但是该算法时间复杂度较高,无法通过全部样例
第二思路:
我们仔细读题不难发现,实际上由输入的数列变化得到的斐波那契数列必然是“起点”为1的斐波那契数列的倍数,那么,我们只需对比输入数列的每一个元素与“起点是1的斐波那契数列”的倍数关系,找到出现的倍数关系次数最多的数,此时将其他不是该倍数关系的数进行更改即可
#include<iostream> #include<climits> using namespace std; #define int long long const int MAX=1e6+10;//注意范围 int f[MAX]; int arr[MAX]; signed main(){ int n,ma=INT_MIN,ans; cin>>n; f[0]=f[1]=1; for(int i=2;i<n;i++){ f[i]=f[i-1]+f[i-2];//得到正常的斐波那契数列 } for(int i=0;i<n;i++){ int temp; cin>>temp; if(temp>ma)ma=temp;//得到所有元素的最大元素值 int num=temp%f[i]; if(num==0){ arr[temp/f[i]]++;//对应倍数进行计数 } } int maxx=INT_MIN; for(int i=1;i<=ma;i++){//找到出现次数最多的倍数 if(arr[i]>maxx){ maxx=arr[i]; } } ans=n-maxx; cout<<ans<<endl; return 0; }