题解: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;
}
posted @ 2026-04-28 17:25  fengjunxiao2014  阅读(23)  评论(1)    收藏  举报