(File IO): input:greatest.in output:greatest.out
时间限制: 1000 ms 空间限制: 131072 KB 具体限制
Goto ProblemSet
题目描述
已知若干个正整数的和为
S
S
S,求这若干个正整数的最小公倍数的最大值。
输入
第一行一个整数
T
T
T,表示测试数据的组数。
接下来
T
T
T行,每行包括一个正整数
S
S
S,表示若干个正整数的和为
S
S
S。
输出
输出
T
T
T行,每行包括一个整数,表示和为
S
S
S的若干个正整数的最小公倍数的最大值。
样例输入
2
4
7
样例输出
4
12
数据范围限制
样例中第一组数据
S
=
4
S=4
S=4,它能分解成
S
=
1
+
1
+
1
+
1
,
S
=
1
+
1
+
2
,
S
=
1
+
3
,
S
=
2
+
2
,
S
=
4
S=1+1+1+1,S=1+1+2,S=1+3,S=2+2,S=4
S=1+1+1+1,S=1+1+2,S=1+3,S=2+2,S=4,很明显
S
=
4
S=4
S=4时最小公倍数为
4
4
4,是所有情况中最小公倍数最大的;第二组数据
S
=
7
S=7
S=7,它能分解成
S
=
3
+
4
S=3+4
S=3+4,
3
3
3和
4
4
4的最小公倍数是
12
12
12,也是所有情况中最小公倍数最大的。
提示
40
40
40%的数据:
S
≤
100
S≤100
S≤100;
80
80
80%的数据:
S
≤
330
S≤330
S≤330,结果不会超过
l
o
n
g
l
o
n
g
long long
longlong类型;
100
100
100%的数据:
2
≤
S
≤
500
,
T
≤
10
2≤S≤500,T≤10
2≤S≤500,T≤10,结果不会超过
25
25
25位整数。
解题思路
心路历程:
开始看题
嗯……压根想不出任何方法。。。
再留意数据范围,我 (哔——),满分还要高精度?
(弃疗中………………)。。
最后膜拜巨老
l
z
h
lzh
lzh。。。
21
:
45
21:45
21:45分竟然过了。。
好吧,回归正题。。
首先我们明白,两个数的乘积等于两个数的最小公倍数乘最大公约数,
其次,我们还能想到,只要两个数所拥有的质因数不同,那么最大公约数也就很小,反之最大公约数就很大!!
(证明:x1+y1<x1*y1(2<=x1,y1),我们就可以分解质因数)
我们可以把题目变成一个背包问题
S
S
S是背包的总容量,每个质因数和它的次幂都是一件物品,这些物品重量是它本身,价值是它本身乘原来的价值,
我们再根据上面所说的,两个数所拥有的质因数要不一样,所以,一个质数的次幂只能取一个。。
动态转移方程:
f
[
i
]
=
m
a
x
f
[
i
−
j
k
]
∗
j
k
(
j
k
<
=
i
)
f[i]=max{f [ i - j ^ k ] * j ^ k}(j ^ k<=i)
f[i]=maxf[i−jk]∗jk(jk<=i)
(下面附上我那很长的代码)
代码
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
int t,n,zs[600],m,a[600][50],s,p,c[50];
bool flag;
void ch(int x,int y)
{
memset(c,0,sizeof(c));
int g=0;
for(int i=49; i>=1; i--)
{
c[i]=a[x][i]*y+g;
g=c[i]/10;
c[i]%=10;
}
}
bool hh(int x)
{
int i=1;
while(a[x][i]==0)i++;
i=49-i;
int j=1;
while(c[j]==0)j++;
j=49-j;
if(i>j)return 0;
if(j>i)return 1;
for(int ii=i; ii<=49; ii++)
{
if(a[x][ii]>c[ii])return 0;
if(c[ii]>a[x][ii])return 1;
}
}
int main()
{
freopen("greatest.in","r",stdin);
freopen("greatest.out","w",stdout);
for(int i=2; i<=501; i++)
{
flag=1;
for(int j=1; j<=t; j++)
{
if(i%zs[j]==0)
{
flag=0;
break;
}
}
if(flag==1)
{
zs[++t]=i;
}
}
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%d",&m);
memset(a,0,sizeof(a));
for(int i=0; i<=m; i++)
a[i][49]=1;
for(int j=1; j<=t; j++)
{
for(int i=m; i>=1; i--)
{
s=zs[j];
for(int k=1; s<=i; s*=zs[j])
{
ch(i-s,s);
if(hh(i))
{
for(int q=1; q<=49; q++)
a[i][q]=c[q];
}
}
}
}
p=1;
while(a[m][p]==0)p++;
while(p<=49)
{
cout<<a[m][p];
p++;
}
cout<<endl;
}
return 0;
}