題意 題目鏈接 求出把$n$分解為斐波那契數的方案數,方案兩兩不同的定義是分解出來的數不完全相同 Sol 這種題,直接爆搜啊。。。 打表後不難發現$<=1e18$的fib數只有88個 最先想到的應該是直接把$n$加入到搜索狀態里,然後枚舉能被分成哪些 但是這樣分解出來的數可能會有重覆的,因此我們還要 ...
題意
求出把$n$分解為斐波那契數的方案數,方案兩兩不同的定義是分解出來的數不完全相同
Sol
這種題,直接爆搜啊。。。
打表後不難發現$<=1e18$的fib數只有88個
最先想到的應該是直接把$n$加入到搜索狀態里,然後枚舉能被分成哪些
但是這樣分解出來的數可能會有重覆的,因此我們還要把當前考慮到第幾個數也加入到狀態里。
不難得到以下代碼
但是很顯然會T飛。
優化一下,只考慮當前的fib數對答案的貢獻,
也就是搜兩種情況:
1、用該數分解
2、不用該數分解
代碼是這樣的
然而還是會T飛。
繼續剪枝。
根據斐波那契的性質$\sum_{i = 1}^n f_i = f_{n+2} -1$
因此我們想要用前$ti - 1$個合成$x$,必須滿足$x < f_{ti+1}$。
然後就A了qwq
// luogu-judger-enable-o2 #include<cstdio> #include<iostream> #include<map> #define Pair pair<int, int> #define MP(x, y) make_pair(x, y) #define fi first #define se second #define int long long #define ull unsigned long long using namespace std; const int MAXN = 1e5 + 10; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int f[MAXN], tot, lim, dp[MAXN], N; map<Pair, int> mp; int dfs(int x, int ti) { if(mp.find(MP(x, ti)) != mp.end()) return mp[MP(x, ti)]; if(x == 0) return 1; int ans = 0; /*for(int i = ti; i >= 1; i--) { if(x - f[i] >= 0) ans += dfs(x - f[i], i - 1); //else break; }*/ if(x - f[ti] >= 0) ans += dfs(x - f[ti], ti - 1); if(x < f[ti + 1]) ans += dfs(x, ti - 1); return mp[MP(x, ti)] = ans; } main() { lim = 1e18; f[1] = 1; f[2] = 2; for(int i = 3; i; i++) { f[i] = f[i - 1] + f[i - 2]; if(f[i] > lim) {tot = i; break;} } N = read(); //dp[0] = 1; cout << dfs(N, tot - 1); return 0; }