【题解】P8808 题解

P8808 题解

思路分析

思维吧,但也不是很难,嘲讽蓝桥杯。

FiF_ia1=a2=ia_1=a_2=i 的斐波那契数列。

首先,斐波那契数列的“形式固定”,即任意一个斐波那契数列,都是 F1F_1 的倍数。

然后,我们就可以看看,每个数是 F1F_1 扩大几倍得到的。

我们开一个桶,对于 x=1Zmaxx=1 \sim Z_{\max}Zmax=106Z_{\max} = 10^6),记录 F1F_1 扩大 xx 倍后,得到的数有多少个与 aa 相同。

那么显然,nn 减去桶记录的数,就是需要改动的数,对于每个计算结果,取最小即可。

怎么去计算桶里的值呢?很简单,我们来个“回手掏”,每次,如果对应的 F1F_1 的数能整除这个原数组里面的数,我们记 kk 为原数组里面的数除以对应的 F1F_1 的数。易证 F1F_1 扩大 kk 倍后,扩大后对应的 FkF_k 的数必然与此数相同,假设这个桶为 cnt\text{cnt},于是此时可以让 cntk\text{cnt}_k 加一。

然后就做完了。

关键代码

int n;
cin >> n;
f[1] = f[2] = 1;
for(int i = 3;i <= 1000000;i++)
{
    f[i] = f[i - 1] + f[i - 2]; //求 F1
}
for(int i = 1;i <= n;i++)
{
    int t;
    cin >> t;
    if(t % f[i] == 0) //统计桶
    {
        cnt[t / f[i]]++;
    }
} 
int minv = numeric_limits<int>::max(); //相当于 INT_MAX
for(int i = 1;i <= 1000000;i++)
{
    minv = min(minv, n - cnt[i]); //求最小
}
cout << minv << endl;
posted @ 2023-09-14 22:39  邻补角-SSA  阅读(8)  评论(0)    收藏  举报  来源