noip2000 乘积最大

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了noip2000 乘积最大相关的知识,希望对你有一定的参考价值。

问题转述:
给出一个长度N的数字串,要求使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。
分析:
动态规划解题。转移方程为:

f[i,k]=Maxf[j,k-1]*s[j+1,i] (j<i)
测试数据
6 1
101010 10100
8 4
321044105 5166000
8 3
22222222 234256
9 5
7777777777 1722499009
我的程序只能过一组 麻烦讲一下我的动规错到哪了 谢谢!
program t2(input,output);
var
ans:array[1..40,0..6]of int64;
str:string;
N,KK,i,j,k:integer;
num1,num2:int64;
procedure max(i,k:integer);
var
ii,num:integer;
temp:int64;
begin
for ii:= 1 to i-1 do
begin
val(copy(str,ii+1,i-ii),num);
temp:= ans[ii,k-1]*num;
if temp>ans[i,k] then ans[i,k]:=temp;
end;
end;
begin
fillchar(ans,sizeof(ans),0);
assign(input,'d:\t2.in');
reset(input);
readln(input,N,KK);
read(input,str);
close(input);
for i:= 1 to n do
begin
val(copy(str,1,i),num1);
ans[i,0]:=num1;
end;
for k:= 1 to KK do
for i:= k+1 to n do
max(i,k);

writeln(ans[i,k]);
end.

需要高精度 算法没错 标程如下:

PROGRAM Maximum(input,output);
CONST maxn=40;
maxm=250;
VAR n,k,i,j,r:byte;
s:STRING[maxn];
tmp,ans:STRING[maxm];
f:ARRAY[1..maxn,boolean] OF STRING[maxm];
a,b,c:ARRAY[1..maxn] OF byte;
FUNCTION Mul(s1,s2:STRING[maxm]):STRING[maxm];
VAR l1,l2,l,i,j:byte;
BEGIN
fillchar(a,sizeof(a),0);
fillchar(b,sizeof(b),0);
fillchar(c,sizeof(c),0);
l1:=length(s1); l2:=length(s2);
FOR i:=1 TO l1 DO a[i]:=ord(s1[l1+1-i])-48;
FOR i:=1 TO l2 DO b[i]:=ord(s2[l2+1-i])-48;
FOR j:=1 TO l2 DO
FOR i:=1 TO l1 DO BEGIN
inc(c[i+j-1],a[i]*b[j]);
IF c[i+j-1]>9 THEN BEGIN
inc(c[i+j],c[i+j-1] DIV 10);
c[i+j-1]:=c[i+j-1] MOD 10
END;
END;
l:=l1+l2; WHILE (l>0) AND (c[l]=0) DO dec(l);
IF l=0 THEN l:=1;
Mul:='';
FOR i:=l DOWNTO 1 DO
Mul:=Mul+chr(c[i]+48)
END;
FUNCTION Greater(s1,s2:STRING[maxm]):boolean;
VAR l1,l2,k:byte;
BEGIN
l1:=length(s1); l2:=length(s2);
IF l1>l2 THEN EXIT(TRUE);
IF l1<l2 THEN EXIT(FALSE);
k:=1;
WHILE s1[k]=s2[k] DO inc(k);
IF s1[k]>s2[k] THEN EXIT(TRUE) ELSE EXIT(FALSE)
END;
BEGIN
assign(input,'d:\t2.in'); reset(input);
assign(output,'d:\t2.out'); rewrite(output);
readln(n,k);
readln(s);
FOR i:=2 TO n DO BEGIN
f[i,TRUE]:='0';
FOR j:=1 TO i-1 DO BEGIN
tmp:=Mul(copy(s,1,j),copy(s,j+1,i-j));
IF Greater(tmp,f[i,TRUE]) THEN f[i,TRUE]:=tmp
END;
END;
FOR r:=2 TO k DO
FOR i:=r+1 TO n DO BEGIN
f[i,odd(r)]:='0';
FOR j:=r TO i-1 DO BEGIN
tmp:=Mul(f[j,NOT odd(r)],copy(s,j+1,i-j));
IF Greater(tmp,f[i,odd(r)]) THEN f[i,odd(r)]:=tmp
END
END;
writeln(f[n,odd(k)]);
close(input); close(output)
END.
参考技术A 可以上我的博客看看
http://blog.sina.com.cn/s/blog_63d0cab00100lc0j.html

[NOIP2000] 提高组 洛谷P1018 乘积最大

 

 

题目描述

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

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

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

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

1) 3*12=36

2) 31*2=62

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

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

输入输出格式

输入格式:

 

程序的输入共有两行:

第一行共有2个自然数N,K(6≤N≤40,1≤K≤6)

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

 

输出格式:

 

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

 

输入输出样例

输入样例#1:
4  2
1231
输出样例#1:
62

说明

NOIp2000提高组第二题

 

动态规划。

设f[乘号][前j个数]=最大乘积。每次枚举添加乘号的区间,求最大值即可。

 1 /*by SilverN*/
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 using namespace std;
 8 const int mxn=60;
 9 char s[300];
10 int num[mxn][mxn];
11 int gt(int i,int j){
12     if(num[i][j])return num[i][j];
13     int x=0;
14     for(int k=i;k<=j;k++){
15         x=x*10+s[k]-0;
16     }
17     return num[i][j]=x;
18 }
19 int f[mxn][mxn];
20 int n,K;
21 int main(){
22     scanf("%d%d",&n,&K);
23     scanf("%s",s+1);
24     int i,j;
25     for(i=1;i<=n;i++)f[0][i]=gt(1,i);
26     for(int k=1;k<=K;k++){
27         for(i=1;i<=n;i++){
28             for(j=i;j>=k;--j){
29                 f[k][i]=max(f[k][i],f[k-1][j-1]*gt(j,i));
30             }
31         }
32     }
33     printf("%d\n",f[K][n]);
34     return 0;
35 }

 

以上是关于noip2000 乘积最大的主要内容,如果未能解决你的问题,请参考以下文章

noip2000 乘积最大

NOIP2000乘积最大[序列DP]

NOIp2000 乘积最大

RQNOJ 311 [NOIP2000]乘积最大:划分型dp

P1018 [NOIP2000 提高组] 乘积最大

[NOIP2000] 提高组 洛谷P1018 乘积最大