题解:B4515 [四川青少年 C++ 算法设计大赛 2025] 圆度
题解:B4515 [四川青少年 C++ 算法设计大赛 2025] 圆度
前言
思路讲解
先考虑十进制下如何判断一些数的乘积末尾有几个 \(0\)。由于十进制是满十进一,我们思考哪几个质数相乘等于 \(10\),其实也就是分解质因数。发现 \(2 \times 5=10\),所以我们就考虑 \(2\) 和 \(5\) 的个数即可。
由于 \(2 \times 3=6\),所以在六进制下,\(2 \times 3=10\),我们考虑 \(2\) 和 \(3\) 的个数,这时候我们发现,选出 \(k\) 个数使他们乘积的质因数 \(2\) 和 \(3\) 的个数最小值最大,是一个经典的背包问题。
AC Code
#include <bits/stdc++.h>
using namespace std;
const int LG = 30;
const int N = 210, M = N * LG;
int n, k, ans, cnt2[N], cnt3[N], dp[N][M], x;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin >> n >> k;
for (int i = 1; i <= n; i++)
{
cin >> x;
while (x % 2 == 0)
{
cnt2[i]++;
x /= 2;
}
while (x % 3 == 0)
{
cnt3[i]++;
x /= 3;
}
}
memset(dp, -1, sizeof(dp));
dp[0][0] = 0;
for (int i = 1; i <= n; i++)
{
for (int j = k; j >= 1; j--)
{
for (int l = n * LG; l >= cnt2[i]; l--)
{
if (dp[j - 1][l - cnt2[i]] == -1)
{
continue;
}
dp[j][l] = max(dp[j][l], dp[j - 1][l - cnt2[i]] + cnt3[i]);
}
}
}
for (int i = 1; i <= n * 10; i++)
{
ans = max(ans, min(i, dp[k][i]));
}
cout << ans;
return 0;
}

浙公网安备 33010602011771号