题目 | 简单的加法乘法计算题
2023 年华中科技大学程序设计竞赛新生赛
A - 简单的加法乘法计算题
https://www.luogu.com.cn/problem/P9769?contestId=138479
题目
JokerShaco 有一个数字
- 选择
中的一个元素 ,令 加上 。 - 选择
中的一个元素 ,令 乘以 。
已知
输入
第一行包含三个整数
第二行包含
输出
输出一个整数,表示让
样例
样例输入 #1
10 3 1
2
样例输出 #1
3
样例输入 #2
100 6 3
2 3 5
样例输出 #2
3
题解
动态规划
朴素的动态规划思想很好理解:
状态表示
从 变化到 需要的步数
状态转移
操作: 操作: (前提是 )
代码片段如下:
for (int i = n + 1; i <= b; i++)
{
for (int j = 1; j <= n; j++)
dp[i] = min(dp[i], dp[i - j] + 1);
for (int j = 1; j <= m; j++)
if (i % b[j] == 0)
dp[i] = min(dp[i], dp[i / b[j]] + 1);
}
容易得到,时间复杂度为:
根据
优化复杂度
从上文可知,每次转移时,需要花费
对于滑动窗口最值问题,直接使用单调队列即可解决了。单调队列的复杂度为
代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
constexpr int MAXN = 5e6 + 10;
int dp[MAXN];
void solve()
{
memset(dp, 0x3f, sizeof(dp));
int y, n, m;
cin >> y >> n >> m;
vector<int> b(m);
for (int i = 0; i < m; i++)
cin >> b[i];
deque<int> dque;
for (int i = 1; i <= n; i++)
{
dp[i] = 1;
dque.push_back(i);
}
for (int i = n + 1; i <= y; i++)
{
while (dque.size() && dque.front() + n < i)
dque.pop_front();
for (int j = 0; j < m; j++)
if (i % b[j] == 0)
dp[i] = min(dp[i], dp[i / b[j]] + 1);
dp[i] = min(dp[i], dp[dque.front()] + 1);
while (dque.size() && dp[dque.back()] > dp[i])
dque.pop_back();
dque.push_back(i);
}
cout << dp[y] << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
// cin >> t;
while (t--)
solve();
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi