题目描述
已知若干个正整数的和为S,求这若干个正整数的最小公倍数的最大值。
输入
第一行一个整数T,表示测试数据的组数。
接下来T行,每行包括一个正整数S,表示若干个正整数的和为S。
输出
输出T行,每行包括一个整数,表示和为S的若干个正整数的最小公倍数的最大值。
样例输入
2
4
7
样例输出
4
12
数据范围限制
样例中第一组数据S=4,它能分解成S=1+1+1+1,S=1+1+2,S=1+3,S=2+2,S=4,很明显S=4时最小公倍数为4,是所有情况中最小公倍数最大的;第二组数据S=7,它能分解成S=3+4,3和4的最小公倍数是12,也是所有情况中最小公倍数最大的。
提示
40%的数据:S≤100;
80%的数据:S≤330,结果不会超过long long类型;
100%的数据:2≤S≤500,T≤10,结果不会超过25位整数。
害人不浅的题啊!
心路历程:
开始看题
嗯……
果断暴力,压根想不出任何方法
再留意数据范围,我 (哔——),满分还要高精度?
(弃疗中………………)
后来听神犇讲后,恍然大悟
于是,开码!
经过我5个小时的努力奋斗,在改掉一个又一个错误后,在9:45,终于AC啦!
思路:
首先我们明白,两个数的乘积等于两个数的最小公倍数乘最大公约数,
其次,我们还能想到,只要两个数所拥有的质因数不同,那么最大公约数也就很小,反之最大公约数就很大!!
我们可以把题目变成一个背包问题
S是背包的总容量,每个质因数和它的次幂都是一件物品,这些物品重量是它本身,价值是它本身乘原来的价值,
我们再根据上面所说的,两个数所拥有的质因数要不一样,所以,一个质数的次幂只能取一个
还要注意高精度不要打错了!!
(下面附上我那很长的代码)
代码:
type
arr=array[0..31]of longint;
var
zhi:array[0..1001,0..31]of longint;
n,i,j,k,x,y,z,s,ls,p,l:longint;
st:string;
a:array[0..31]of longint;
f:array[0..1001,0..501,0..31]of longint;
b:boolean;
function max(x,y:longint):longint;
begin
if x<y then exit(y)
else exit(x);
end;
function zhuan(a:arr):longint;
var
i,j,k,x,y,z,s,ls:longint;
begin
x:=0;
for i:=a[0] downto 1 do
x:=x*10+a[i];
exit(x);
end;
function jian(x:longint;a:arr):longint;
var
b,c:arr;
i,j,k,y,z,s,ls:longint;
begin
fillchar(c,sizeof(c),0);
fillchar(b,sizeof(b),0);
while x<>0 do
begin
inc(b[0]);
b[b[0]]:=x mod 10;
x:=x div 10;
end;
x:=max(a[0],b[0]);
for i:=1 to x do
begin
c[i]:=c[i]+b[i]-a[i];
if c[i]<0 then
begin
inc(c[i],10);
dec(c[i+1]);
end;
end;
c[0]:=x;
while (c[0]>0)and(c[c[0]]=0) do
dec(c[0]);
if c[c[0]]<0 then exit(maxlongint)
else
begin
x:=0;
for i:=c[0] downto 1 do
x:=x*10+c[i];
exit(x);
end;
end;
function pd(a,b:arr):boolean;
var
i,j,k,x,y,z,s,ls:longint;
begin
if a[0]>b[0] then exit(true);
if a[0]<b[0] then exit(false);
for i:=a[0] downto 1 do
begin
if a[i]>b[i] then exit(true);
if b[i]>a[i] then exit(false);
end;
exit(true);
end;
function cheng(a:arr;p:longint):arr;
var
c,b:arr;
i,j,k,x,y,z,s,ls:longint;
begin
fillchar(c,sizeof(c),0);
fillchar(b,sizeof(b),0);
while p<>0 do
begin
inc(b[0]);
b[b[0]]:=p mod 10;
p:=p div 10;
end;
for i:=1 to a[0] do
begin
x:=0;
for j:=1 to b[0] do
begin
c[i+j-1]:=a[i]*b[j]+x+c[i+j-1];
x:=c[i+j-1] div 10;
c[i+j-1]:=c[i+j-1] mod 10;
end;
c[i+j]:=x;
end;
c[0]:=a[0]+b[0];
while c[c[0]]=0 do
dec(c[0]);
exit(c);
end;
begin
for i:=2 to 501 do
begin
b:=true;
for j:=2 to trunc(sqrt(i)) do
if i mod j=0 then
begin
b:=false;
break;
end;
if b then
begin
str(i,st);
inc(zhi[0,0]);
for j:=length(st) downto 1 do
begin
inc(zhi[zhi[0,0],0]);
zhi[zhi[0,0],zhi[zhi[0,0],0]]:=ord(st[j])-48;
end;
end;
end;
readln(n);
for i:=1 to n do
begin
readln(st);
a[0]:=length(st);
for j:=length(st) downto 1 do
a[a[0]-j+1]:=ord(st[j])-48;
val(st,x);
fillchar(f,sizeof(f),0);
for j:=0 to 501 do
begin
f[0,j,0]:=1;
f[0,j,1]:=1;
end;
for j:=1 to zhi[0,0] do
begin
p:=zhuan(zhi[j]);
ls:=1;
f[j]:=f[j-1];
for l:=1 to 9 do
begin
ls:=ls*p;
if ls>999 then break;
for k:=0 to x do
begin
if k>=ls then
begin
if pd(f[j,k],cheng(f[j-1,k-ls],ls))=false then
f[j,k]:=cheng(f[j-1,k-ls],ls);
end;
end;
end;
end;
for j:=f[zhi[0,0],x,0] downto 1 do
write(f[zhi[0,0],x,j]);
writeln;
end;
end.