题解:B4515 [四川青少年 C++ 算法设计大赛 2025] 圆度
先说本题的核心理论:
如果一个六进制数末尾有
举个例子,如
所以我们要尽可能拿有因子
我们只要先将
我们可以设计
::::success[AC 代码]
#include<bits/stdc++.h>
using namespace std;
int a2[201], a3[201];
int dp[201][1001];
int main() {
int n, k, ans = 0;
scanf("%d%d", &n, &k);
for(int i = 1, x; i <= n; i++) {
scanf("%d", &x);
while(x % 2 == 0) {
a2[i]++;
x /= 2;
}
while(x % 3 == 0) {
a3[i]++;
x /= 3;
}
// a2[i] 用来存储 a[i] 的因子 2 的个数,a3[i] 用来存储 a[i] 的因子 3 的因子 3 的个数。
}
// 初始化,不要跟我一样初始化成INT_MIN,会WA
memset(dp, -0x3f, sizeof dp);
dp[0][0] = 0;
/*
将任意的 for 循环调换
或如把:for(int j = k; j >= 1; j--) ->
for(int j = 1; j <= k; j++) 都会WA
*/
for(int i = 1; i <= n; i++) {
// 枚举每一个数
for(int j = k; j >= 1; j--) {
for(int l = 1000; l >= a2[i]; l--) {
// 枚举可能的因数 2 的数量
dp[j][l] = max(dp[j][l], dp[j-1][l-a2[i]] + a3[i]);
// 类似01背包的状态转移方程
if(j == k) ans = max(min(dp[j][l], l), ans);
// 在选了 k 个数(第二层循环)后在因数 2 的个数和因数 3 的个数中取更小值
}
}
}
printf("%d", ans);
return 0;
}
::::