#温馨提示:此文章使用的是MD编辑器,在小程序上查看可能会出现乱码,敬请谅解
【题目链接】P10095 [ROIR 2023 Day 1] 斐波那契乘积
我们可以采用递归的方法解决斐波那契数乘积的问题。首先计算足够多的斐波那契数存入数组
a
a
a 中,然后针对每个输入的自然数
n
n
n ,利用递归函数search
试图将
n
n
n 拆分成若干个大于
1
1
1 的斐波那契数的乘积。在搜索过程中,一旦找到能够整除
n
n
n 的斐波那契数
a
[
x
]
a[x]
a[x] ,就将其从
n
n
n 中约掉,并对剩余的部分继续递归分解。
请注意以下易错点:
- 务必确保生成的斐波那契数列足以覆盖题目给出的所有可能的 n n n 值,否则可能导致错误的答案。
- 递归搜索时要注意边界条件的判断,防止陷入无限循环或者无效搜索。
- 在
while
循环里正确检查和处理 n n n 是否可以被当前斐波那契数整除,且每次整除后更新临时变量 t m p tmp tmp 。- 在搜索过程中每当找到一种新的分解方式时,要确保及时更新答案变量 a n s ans ans 。
AC代码如下
#include <bits/stdc++.h>
#define ll long long // 用ll代替long long以简化代码
using namespace std;
ll a[105], ans; // 定义常量数组a来存储斐波那契数列,以及答案变量ans
// 搜索函数search,用于递归地分解n为斐波那契数的乘积
// x代表斐波那契数列的索引,从2开始,n代表当前要分解的数值
void search(ll x, ll n) {
if (n == 1) { // 基础情况:当n等于1时,找到了一种合法的分解方式,增加答案计数器
ans++;
return;
}
if (a[x] > n) return; // 若当前斐波那契数a[x]大于n,则不可能继续分解,直接返回
ll tmp = n; // 循环分割过程:尝试将n不断除以a[x],直到不能再整除为止
while (tmp % a[x] == 0) {
search(x + 1, tmp / a[x]); // 递归地处理除以a[x]之后的余数部分
tmp /= a[x];
}
search(x + 1, n); // 若不能整除,直接进入下一位斐波那契数进行搜索
}
int main() {
ll t, n, len=1; // 初始化斐波那契数列
a[0] = 1;
a[1] = 1;
while (a[len] <= 1000000000000000000) { // 生成斐波那契数列至足够大的数,以覆盖题目所给的最大范围
a[len + 1] = a[len] + a[len - 1];
len++;
}
cin >> t; // 读取测试数据组数
while (t--) { // 遍历所有测试数据
cin >> n; // 读取每个自然数n
ans = 0; // 重置答案计数器
search(2, n); // 开始搜索并统计n可以表示为斐波那契数乘积的方式数
cout << ans << endl; // 输出答案
}
return 0;
}
#普通版先鸽着