T1:倍数序列3

本题难度中等,思路和 LIS 类似,用 dp[i] 表示以 ai 结尾的倍数序列的个数。如果 aiaj 的倍数,倍数序列个数就是 dp[j],枚举所有 j 求和即可得到 dp[i] 。时间复杂度:O(n2)

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
int main() {
int n;
cin >> n;
vector<ll> a(n);
rep(i, n) cin >> a[i];
sort(a.begin(), a.end());
ll ans = 0;
vector<ll> dp(n);
rep(i, n) {
dp[i] = 1;
rep(j, i) if (a[i]%a[j] == 0) {
dp[i] += dp[j];
}
ans += dp[i];
}
cout << ans << '\n';
return 0;
}

T2:火箭载荷

本题难度中等,可以化为01背包模板。将升空条件写出,做变形之后,通过选取适当的量作为物品的大小和价值,就可以化为01背包模板。
dp[v] 表示载荷使用 v 体积后的最大重量

转移方程:
dp[j]=max{dp[jvi]+wi}

还需满足条件 W+dp[j]+(Vj)c(Vj)k

但这里以体积作为代价去求最大重量,会把本来合法的较小一些的方案给忽略掉,将对答案有致命的影响

重量固定时,体积尽可能小
dp[j] 表示载荷重量恰好为 j 时,对应的最小体积

转移方程:

dp[j]=min{dp[jwi]+vi}

由于这个状态没有转移就是无解的,为了使得它有解,应该尽可能的去转移
设置 dp 的初值为无穷大
dp[0]=0

还需满足条件:W+j+(Vdp[j])c(cdp[j])k

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
inline void chmin(int& x, int y) { if (x > y) x = y; }
int main() {
int n, W, V, c, k;
cin >> n >> W >> V >> c >> k;
const int MX = 100001;
const int INF = 1001001001;
vector<int> dp(MX, INF);
dp[0] = 0;
rep(i, n) {
int w, v;
cin >> w >> v;
for (int j = MX-1; j >= w; --j) {
chmin(dp[j], dp[j-w]+v);
}
}
int ans = -1;
rep(i, MX) {
if (dp[i] <= V and (V-dp[i])*k >= W+i+(V-dp[i])*c) {
ans = i;
}
}
cout << ans << '\n';
return 0;
}