最大最小公倍数

题目描述

已知若干个正整数的和为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.
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值