整数划分
时间限制: 1 Sec 内存限制: 128 MB
题目描述
如何把一个正整数N(N长度<20)划分为M(M>1)个部分,使这N个部分的乘积最大。N、M从键盘输入,输出最大值及一种划分方式。
输入数据:
第一行一个正整数T(T<=10000),表示有T组数据。
接下来T行每行两个正整数N,M。
输入
第一行一个正整数T(T<=10000),表示有T组数据。
接下来T行每行两个正整数N,M。
输出
对于每组数据
第一行输出最大值。
第二行输出划分方案,将N按顺序分成M个数输出,两个数之间用空格格开。
样例输入
1
199 2
样例输出
171
19 9
题解
- f[i,j]:取i到j的数字组成的数
- dp[i,j,1]:前i个数字分成j个乘积的最大值
- dp[i,j,2]:记录dp[i,j,1]的值是由谁传递来的
- dp[i,j,1]=max(dp[i,j,1],dp[k,j−1]∗f[k+1,i]) 1≤k≤i−1
- dp[i,j,2]=k dp[i,j,1]<dp[k,j−1]∗f[k+1,i]
var
dp:array[0..20,0..20,1..2]of int64;
f:array[0..20,0..20]of int64;
x:array[0..20]of string;
i,j,k,l:longint;
t,m,s,len:longint;
n,v:int64;
st:string;
function max(a,b:int64):int64;
begin
if a>b
then exit(a)
else exit(b);
end;
begin
readln(t);
for l:=1 to t do
begin
readln(n,m); str(n,st);
for i:=1 to length(st) do
for j:=1 to length(st) do
val(copy(st,i,j-i+1),f[i,j]);
for i:=1 to 20 do
for j:=1 to 20 do
if (j=1)and(i<=length(st))
then dp[i,j,1]:=f[1,i]
else dp[i,j,1]:=0;
for i:=2 to length(st) do
for j:=2 to m do
for k:=1 to i-1 do
begin
{dp[i,j,1]:=max(dp[i,j,1],dp[k,j-1,1]*f[k+1,i]);}
if dp[k,j-1,1]*f[k+1,i]>dp[i,j,1]
then
begin
dp[i,j,1]:=dp[k,j-1,1]*f[k+1,i];
dp[i,j,2]:=k;
end;
end;
writeln(dp[length(st),m,1]);
if dp[length(st),m,1]=0
then begin
for i:=1 to length(st) do
write(st[i],' ');
writeln;
end
else begin
i:=length(st); j:=m; len:=0;
while j>1 do
begin
s:=dp[i,j,2];
inc(len);
x[len]:=copy(st,s+1,length(st)-s);
st:=copy(st,1,s);
i:=s; dec(j);
end;
inc(len); x[len]:=st;
for i:=len downto 1 do
write(x[i],' ');
writeln; end;
end;
end.