有一个数x, 0<=x<=1000, 把它拆分成几个数的和,x1+x2+......xn=x,使得x1,x2,x3.....xn的最小公倍数最大,
要求输入这个数 x,输出最小公倍数 S。
题目来源:
http://community.csdn.net/Expert/TopicView.asp?id=5086754
http://bbs.xilu.com/cgi-bin/bbs/view?forum=rd&message=3761
可以通过使用动态规划来计算
首先容易证明,存在一种达到最大值的拆分方案,使得每个xi最多只有一个素因子(也就是说xi必然是1,素数或素数的幂),而且不同的xi之间互素(它们的素因子不同)。
然后就可以使用动态规划来计算。
中第k步是计算出x1,x2,...,xn使得
x1+x2+...+xn = x
x1,x2,...,xn的所有素因子都是前k个素数, (p1=2,p2=3,p3=5,...,pk)
x1,x2,...,xn的最小公倍数最大时的情况.
所以我每步添加一个新数(使用x+y的情况),必然有这两个数互素( (x,y)=1 )
为了简单起见,程序中用了gmp
#include <gmp.h>
#include <stdio.h>
#define MAX 10000
mpz_t mul[2][MAX+1];
mpz_t *muls1;
mpz_t *muls2;
int prime_list[MAX+1];
int prime_count;
mpz_t t;
void init_prime(){
int i,j;
prime_list[0]=prime_list[1]=1;
for(i=2;i<=MAX;i++){
if(!prime_list[i]){//if prime
for(j=i*i;j<=MAX;j+=i){
prime_list[j]=1;
}
}
}
for(i=0;i<=MAX;i++){
if(!prime_list[i]){
prime_list[prime_count++]=i;
}
}
}
int main(){
int i,j;
for(i=0;i<=MAX;i++)
{
mpz_init(mul[0][i]);
mpz_init(mul[1][i]);
mpz_set_ui(mul[0][i],0);
}
mpz_set_ui(mul[0][0],1);
muls1 = mul[0];
muls2 = mul[1];
init_prime();
mpz_init(t);
for(i=0;i<prime_count;i++){
int p = prime_list[i];
for(j=0;j<=MAX;j++){
mpz_set(muls2[j],muls1[j]);
}
while(p<=MAX){
for(j=0;j<=MAX-p;j++){
if(mpz_cmp_ui(muls2[j],0)==0)
continue;
mpz_mul_ui(t, muls2[j],p);
if(mpz_cmp(t, muls1[j+p])>0){
mpz_set(muls1[j+p],t);
}
}
p*=prime_list[i];
}
}
mpz_set_ui(muls1[1],1);
for(i=1;i<=MAX;i++){
if(mpz_cmp(muls1[i-1],muls1[i])>0){
mpz_set(muls1[i],muls1[i-1]);
}
}
for(i=2;i<=MAX;i++){
if(mpz_cmp(muls1[i-1],muls1[i])==0){
mpz_set_ui(muls1[i],0);
}
}
for(i=1;i<=MAX;i++){
int c;
if(mpz_cmp_ui(muls1[i],0)==0)
continue;
printf("%d, ",i);
mpz_out_str(stdout,10,muls1[i]);
printf(" { ");
for(j=0;j<prime_count;j++){
c=0;
if(mpz_cmp_ui(muls1[i],1)<=0)break;
mpz_gcd_ui(t,muls1[i],prime_list[j]);
while(mpz_cmp_ui(t,1)>0){
mpz_cdiv_qr_ui(muls1[i],t,muls1[i],prime_list[j]);
c++;
mpz_gcd_ui(t,muls1[i],prime_list[j]);
}
if(c==1){
printf("%d ",prime_list[j]);
}else if(c>1){
printf("%d^%d ",prime_list[j],c);
}
}
printf("}/n");
}
return 0;
}