题解:B4219 [常州市程序设计小能手 2023] 数学作业
思路:预处理
代码:
#include <bits/stdc++.h>
#define IS std::cin.tie(nullptr) -> std::ios::sync_with_stdio(false)
#define OS std::cout.tie(nullptr) -> std::ios::sync_with_stdio(false)
#define srnd srand((unsigned int)time(0))
#define rnd rand()
#define save(x) std::fixed << std::setprecision(x)
#define set_0(x) memset(x, 0, sizeof(x))
#define set_false(x) memset(x, false, sizeof(x))
#define set_true(x) memset(x, true, sizeof(x))
#define set_nega1(x) memset(x, -1, sizeof(x))
#define set_Iinf(x) memset(x, 0x7f, sizeof(x))
#define set_Finf(x) memset(x, 7e4, sizeof(x));
#define lc(x) (x << 1)
#define rc(x) (x << 1 | 1)
#define low_bit(x) (x & (-x))
#define __DEBUG__ puts("DEBUG")
using namespace std;
vector <long long> fib;
int dfs(int search, long long cnt) {
if(cnt == 0) {
return 1;
}
int res = 0;
for(int i = search; i < fib.size(); ++i) {
if(cnt - fib[i] < 0) {
return res;
}
res += dfs(i + 1, cnt - fib[i]);//不降原则保证选数不重复
}
return res;
}
signed main() {
IS;
OS;
long long n;
cin >> n;
fib.push_back(1);
fib.push_back(2);
while(fib.back() <= n) {
fib.push_back(fib[fib.size() - 1] + fib[fib.size() - 2]);
}
fib.pop_back();
cout << dfs(0, n);
return 0;
}
然而
所以我们需要剪枝
剪枝1:设数列
得出代码:
#include <bits/stdc++.h>
#define IS std::cin.tie(nullptr) -> std::ios::sync_with_stdio(false)
#define OS std::cout.tie(nullptr) -> std::ios::sync_with_stdio(false)
#define srnd srand((unsigned int)time(0))
#define rnd rand()
#define save(x) std::fixed << std::setprecision(x)
#define set_0(x) memset(x, 0, sizeof(x))
#define set_false(x) memset(x, false, sizeof(x))
#define set_true(x) memset(x, true, sizeof(x))
#define set_nega1(x) memset(x, -1, sizeof(x))
#define set_Iinf(x) memset(x, 0x7f, sizeof(x))
#define set_Finf(x) memset(x, 7e4, sizeof(x));
#define lc(x) (x << 1)
#define rc(x) (x << 1 | 1)
#define low_bit(x) (x & (-x))
#define __DEBUG__ puts("DEBUG")
using namespace std;
vector <long long> fib;//对应k
long long sum_fib = 0;//对应sum
int dfs(int search, long long sum) {//这里跟文中讲得不一样,参数sum = n - t
if(sum <= 0 || sum_fib < sum || search >= fib.size()) {//剪枝1
return sum == 0 ? 1 : 0;
}
sum_fib -= fib[search];
int res = dfs(search + 1, sum - fib[search]) + dfs(search + 1, sum);
sum_fib += fib[search];//利用回溯实现
return res;
}
signed main() {
IS;
OS;
long long n;
cin >> n;
fib.push_back(1);
fib.push_back(2);
while(fib.back() <= n) {
fib.push_back(fib[fib.size() - 1] + fib[fib.size() - 2]);
}
fib.pop_back();
sum_fib = accumulate(fib.begin(), fib.end(), 0ll);
cout << dfs(0, n);
return 0;
}
交上去一看,还是 TLE ,为什么?因为
我们可以发现,现在 TLE 的原因是
得出AC代码:
#include <bits/stdc++.h>
#define IS std::cin.tie(nullptr) -> std::ios::sync_with_stdio(false)
#define OS std::cout.tie(nullptr) -> std::ios::sync_with_stdio(false)
#define srnd srand((unsigned int)time(0))
#define rnd rand()
#define save(x) std::fixed << std::setprecision(x)
#define set_0(x) memset(x, 0, sizeof(x))
#define set_false(x) memset(x, false, sizeof(x))
#define set_true(x) memset(x, true, sizeof(x))
#define set_nega1(x) memset(x, -1, sizeof(x))
#define set_Iinf(x) memset(x, 0x7f, sizeof(x))
#define set_Finf(x) memset(x, 7e4, sizeof(x));
#define lc(x) (x << 1)
#define rc(x) (x << 1 | 1)
#define low_bit(x) (x & (-x))
#define __DEBUG__ puts("DEBUG")
using namespace std;
vector <long long> fib;//对应k
long long sum_fib = 0;//对应sum
int dfs(int search, long long sum) {//这里跟文中讲得不一样,参数sum = n - t
if(sum <= 0 || sum_fib < sum || search >= fib.size()) {//剪枝1
return sum == 0 ? 1 : 0;
}
sum_fib -= fib[search];
int res = dfs(search + 1, sum - fib[search]) + dfs(search + 1, sum);
sum_fib += fib[search];//利用回溯实现
return res;
}
signed main() {
IS;
OS;
long long n;
cin >> n;
fib.push_back(1);
fib.push_back(2);
while(fib.back() <= n) {
fib.push_back(fib[fib.size() - 1] + fib[fib.size() - 2]);
}
fib.pop_back();
sum_fib = accumulate(fib.begin(), fib.end(), 0ll);
reverse(fib.begin(), fib.end());//剪枝2
cout << dfs(0, n);
return 0;
}