社区讨论

悬关,有思路、注释,50分求条

P1018[NOIP 2000 提高组] 乘积最大参与者 2已保存回复 5

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
5 条
当前快照
1 份
快照标识符
@mhqm6bn5
此快照首次捕获于
2025/11/09 02:24
3 个月前
此快照最后确认于
2025/11/16 14:08
3 个月前
查看原帖
CPP
/*
DP思路(实际写了高精):
f[i][j] = 将前i个数分成j份,那j份的积的最大值。
f[i][j] = max (f[i][j], f[l][j - 1] * g[l+1][i]);
l为小于i,大于等于j-1的数,g[x][y]为原数列从x到y的数。
*/
#include <bits/stdc++.h>
using namespace std;
string tim(string &sa, string &sb) {
	if (sa == "") return "0";
	string ans = "";
	int a[45], b[45], c[105], l = sa.size () + sb.size ();
	memset (c, 0, sizeof (c));
	for (int i = 0; i < sa.size (); i++)
		a[sa.size () - i] = sa[i] ^ 48;
	for (int i = 0; i < sb.size (); i++) 
		b[sb.size () - i] = sb[i] ^ 48;
	for (int i = 1; i <= sa.size (); i++) {
		int x = 0;
		for (int j = 1; j <= sb.size (); j++) {
			c[i + j - 1] = x + c[i + j - 1] + a[i] * b[j];
			x = c[i + j - 1] / 10;
			c[i + j - 1] %= 10;
		}
		c[i + sb.size ()] += x;
	}
	while (c[l] == 0 && l > 1)
		l--;
	for (int i = 0; i < l; i++)
		ans += c[l - i] ^ 48;
	return ans;
}//高精乘,返回两数的积。
void qmx (string &a, string b) {
	int la = a.size (), lb = b.size ();
	if (la > lb) return;
	if (la < lb) {
		a = b; return;
	}
	for (int i = 0; i < la; i++) {
		if (a[i] > b[i]) {
			return;
		}
		else {
			a = b;
			return;
		}
	}
}//取两数的最大值,同时因为第一个数是传址的,无需二次赋值。
int n, k;
string s, f[45][10], g[45][45];
int main () {
	cin >> n >> k >> s;
	k++;
	for (int i = n; i; i--)
		s[i] = s[i - 1];//让s索引从1开始。
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= i; j++) {
			if (i == j) g[j][i] = s[i];
			else g[j][i] = g[j][i - 1] + s[i];
		}//预处理从j到i的数。
	f[1][1] = s[1];
	for (int i = 2; i <= n; i++) {
		f[i][i] = tim (f[i - 1][i - 1], g[i][i]);
		f[i][1] = g[1][i];
	}//DP初值
	for (int i = 1; i <= n; i++){
		for (int j = 1; j <= min (i, k); j++) {
			for (int l = j - 1; l < i; l++) {
				qmx (f[i][j], tim (f[l][j - 1], g[l + 1][i]));
			}
		}
	}//DP
	cout << f[n][k] << endl;//输出
	return 0;
}

回复

5 条回复,欢迎继续交流。

正在加载回复...