洛谷P1018乘积最大题解--zhengjun

题目描述

今年是国际数学联盟确定的“ 2000 2000 ――世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰 90 90 周年。在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友 X Z XZ 也有幸得以参加。活动中,主持人给所有参加活动的选手出了这样一道题目:

设有一个长度为 N N 的数字串,要求选手使用 K K 个乘号将它分成 K + 1 K+1 个部分,找出一种分法,使得这 K + 1 K+1 个部分的乘积能够为最大。

同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子:

有一个数字串: 312 312 , 当 N = 3 , K = 1 N=3,K=1 时会有以下两种分法:

  1. 3 × 12 = 36 3 \times 12=36
  2. 31 × 2 = 62 31 \times 2=62

这时,符合题目要求的结果是: 31 × 2 = 62 31 \times 2 = 62

现在,请你帮助你的好朋友 X Z XZ 设计一个程序,求得正确的答案。

输入格式

程序的输入共有两行:

第一行共有 2 2 个自然数 N , K N,K 6 N 40 , 1 K 6 6\le N\le 40,1\le K\le 6

第二行是一个长度为 N N 的数字串。

输出格式

结果显示在屏幕上,相对于输入,应输出所求得的最大乘积(一个自然数)。

输入输出样例

输入 #1
4  2
1231
输出 #1
62

说明/提示

N O I P   2000 NOIP\ 2000 提高组第二题

思路

首先,这是一道动态规划题应该很容易就判断出来。
属于区间 d p dp
f i , j f_{i,j} 表示前 i i 个数字中插入 j j × \times 号的最大乘积。
初始值:
显然: j = 0 j=0 时, f i , j = S 1 S j ; i j f_{i,j}=S_1\cdot\cdot\cdot S_j;i\le j 时, f i , j = 0 ; f_{i,j}=0;
对于其他情况,就枚举最后一个 × \times 号的位置和用了几个 × \times 号,转移方程就是 f i , j = m a x { f k , j 1 × S 1 S j } f_{i,j}=max\{f_{k,j-1}\times S_1\cdot\cdot\cdot S_j\}

最后,本题还要高精度,你们不想打就直接拿我的模板吧。

上代码

#include<bits/stdc++.h>
using namespace std;
/*************************以下为模板***************************/
#define maxn 10005
struct bignum {
	int len,s[maxn];
	char flag;
	bignum() {
		len=1;
		flag='+';
		memset(s,0,sizeof(s));
	}
	bignum (int num) {
		*this=num;
	}
	bignum (const char *num) {
		*this=num;
	}
	bignum operator = (const char *a) {
		len=strlen(a);
		for (int i=1; i<=len; ++i)
			s[i]=a[len-i]-'0';
		return *this;
	}
	bignum operator = (const int num) {
		char a[maxn];
		sprintf(a,"%d",num);
		*this=a;
		return *this;
	}
	bignum operator + (const bignum &a) {
		bignum c;
		c.len=max(len,a.len)+1;
		for (int i=1; i<c.len; ++i) {
			c.s[i]+=(s[i]+a.s[i]);
			c.s[i+1]+=c.s[i]/10;
			c.s[i]%=10;
		}
		if (c.s[c.len]==0)
			c.len--;
		return c;
	}
	bignum operator += (const bignum &a) {
		*this=*this+a;
		return *this;
	}
	bignum operator * (const bignum &a) {
		bignum c;
		c.len+=(len+a.len);
		for (int i=1; i<=len; ++i)
			for (int j=1; j<=a.len; ++j) {
				c.s[i+j-1]+=(s[i]*a.s[j]);
				c.s[i+j]+=(c.s[i+j-1]/10);
				c.s[i+j-1]%=10;
			}
		while (c.s[c.len]==0)
			c.len--;
		return c;
	}
	bignum operator *= (const bignum &a) {
		*this=(*this) * a;
		return *this;
	}
	bool operator < (const bignum &a) const {
		if (len!=a.len)
			return len<a.len;
		for (int i=len; i>=1; --i)
			if (s[i]!=a.s[i])
				return s[i]<a.s[i];
		return false;
	}
	bool operator > (const bignum &a) const {
		return a<*this;
	}
	bool operator <= (const bignum &a) const {
		return !(*this>a);
	}
	bool operator >= (const bignum &a) const {
		return !(*this<a);
	}
	bool operator == (const bignum &a) const {
		return !((*this<a) || (*this>a));
	}
	bool operator != (const bignum &a) const {
		return !(*this==a);
	}
	void change (bignum &a,bignum &b) {
		bignum tmp=a;
		a=b;
		b=tmp;
	}
	bignum operator - (const bignum &a) const {
		bignum b=*this,c;
		if (b<a) {
			c.flag='-';
			c.len=a.len;
			for (int i=1; i<=c.len; ++i) {
				c.s[i]+=(a.s[i]-b.s[i]);
				if (c.s[i]<0) {
					c.s[i]+=10;
					c.s[i+1]-=1;
				}
			}
			while (c.len==0)
				c.len--;
			return c;
		}
		c.len=b.len;
		for (int i=1; i<=c.len; ++i) {
			c.s[i]+=(b.s[i]-a.s[i]);
			if (c.s[i]<0) {
				c.s[i]+=10;
				c.s[i+1]-=1;
			}
		}
		while (c.len==0)
			c.len--;
		return c;
	}
	bignum operator -= (const bignum &a) {
		*this=(*this)-a;
		return *this;
	}
	bignum operator / (const int n) {
		bignum c,b=*this;
		c.len=b.len;
		int x=0;
		for (int i=1; i<=n; ++i) {
			c.s[i]=(x*10+b.s[i])/n;
			x=(x*10+b.s[i])%n;
		}
		while (c.s[c.len]==0)
			c.len--;
		return c;
	}
	bignum operator /= (const int a) {
		*this=*this/a;
		return *this;
	}
};
ostream& operator << (ostream &out,const bignum &x) {
	for (int i=x.len; i>=1; --i)
		printf("%d",x.s[i]);
	return out;
}
bignum bigmax(const bignum &a,const bignum &b){
	return a>b?a:b;
}
/*************************以上为模板***************************/
int n,k;
char s[50];
bignum f[50][10],a[50][50];
int main() {
	scanf("%d%d",&n,&k);
	scanf("%s",s+1);
	for(int i=1;i<=n;i++)
	    for(int j=i;j<=n;j++)
	        a[i][j]=a[i][j-1]*10+(s[j]-'0');
	for(int i=1;i<=n;i++){
		f[i][0]=a[1][i];
		for(int j=1;j<=k;j++)
		    for(int l=j;l<i;l++)
		        f[i][j]=bigmax(f[i][j],f[l][j-1]*a[l+1][i]);
	}
	cout<<f[n][k];
	return 0;
}

谢谢–zhengjun_记得打赞

发布了48 篇原创文章 · 获赞 49 · 访问量 2151

猜你喜欢

转载自blog.csdn.net/A_zjzj/article/details/104318041
今日推荐