移动端 Banners
CF 126D - Fibonacci Sums 题解
766 字
4 分钟
CF 126D - Fibonacci Sums 题解
Done
您已获得最佳的阅读体验!
题目地址:CF 126D
题目难度:省选/NOI-
计算一个整数被分解成若干个各不相等的Fibonacci数列中的数的方案。
前置 齐肯多夫定理
齐肯多夫定理的内容是:
任何正整数都可以被表示成若干不连续的斐波那契数之和(
除外)
而对于一个正整数,我们可以按照二进制分解的策略:先贪心地找到一个最大的
斐波那契数列一般定义为:
类比二进制,齐肯多夫分解是可以用一个
不难发现,按照贪心策略计算出的拆分是不会存在相邻的两个
回归正题
假如我们现在已经得到了一个齐肯多夫拆分,如何计算题目要求的方案总数呢?
可以利用“标准齐肯多夫拆分中不存在相邻 *100*(星号代表任意 *011*。如果在末尾的
注意到要求方案数,考虑动态规划。我们用
接下来考虑当前状态从何而来。如果选择不删当前这一位,答案只能从前一位
如果选择删除这一位,对于接下来的操作,我们仍然可以选择删除或不删除。发现删到最后整个字符串一定是像 101010101 这样交错排列的。于是可以得到:
#include <bits/stdc++.h>
#define N 90using namespace std;
typedef long long ll;
vector<int> pos;ll fib[N];ll dp[N][2];
void init() { fib[1] = fib[2] = 1; for (int i = 3; i < N; i++) fib[i] = fib[i - 1] + fib[i - 2];}
int solve(ll x) { pos.clear(); for (int i = N - 1; i >= 1; i--) { if (!x) break; if (fib[i] <= x) { x -= fib[i]; pos.push_back(i - 1); } } reverse(pos.begin(), pos.end()); return pos.size();}
int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
int t; cin >> t; init(); while (t--) { memset(dp, 0, sizeof dp);
ll x; cin >> x; int len = solve(x); dp[0][0] = 1; dp[0][1] = (pos[0] - 1) / 2; for (int i = 1; i < len; i++) { dp[i][0] = dp[i - 1][0] + dp[i - 1][1]; dp[i][1] = dp[i - 1][0] * ((pos[i] - pos[i - 1] - 1) / 2) + dp[i - 1][1] * ((pos[i] - pos[i - 1]) / 2); } cout << dp[len - 1][1] + dp[len - 1][0] << endl; } return 0;}文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
CF 126D - Fibonacci Sums 题解
https://justpureh2o.cn/articles/126/ 相关文章 智能推荐
1
CF 1728F - Fishermen 题解
题解 2024-08-06
2
CF 1404E - Bricks 题解
题解 2024-08-05
3
P3571 [POI2014] - Supercomputer 题解
题解 2024-08-25
4
SP15648 [APIO10A] - Commando 题解
题解 2024-07-25
5
P11253 [GDKOI2023 普及组] 小学生数学题
题解 2024-11-09
随机文章 随机推荐