给定一个数,分解成k个数之和,使得这K个数公约数最大,最小公倍数也最大。
最大公约数最大,肯定选择除以素数分解后的最小素数。
现在相当于分解质数m使得最小公倍数最大。
用dp[i][j]表示用前i个质数分解和为m最小公倍数最大。
最后一定是2 ^ k1 * 3 ^ k2 * 5 ^ k3....
所以可以写出dp转移出来。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF = 1000000007;
const int maxn = 100007;
long long least;
int vis[maxn], prime[maxn], prime_num;
int ans[maxn], ans_num, temp[maxn];
int pre[156][35000];
double dp[156][35000];
long long big_lcm;
long long n, f;
void getAllPrime() {
memset(vis, 0, sizeof(vis));
for (int i = 2; i <= sqrt(maxn * 1.0); i++) {
if (!vis[i]) {
for (int j = i * i; j < maxn; j += i) {
vis[j] = 1;
}
}
}
prime_num = 0;
for (int i = 2; i < maxn; i++) {
if (!vis[i]) {
prime[++prime_num] = i;
}
}
}
int main() {
// freopen("in.txt", "r", stdin);
long long x;
getAllPrime();
scanf("%I64d", &n);
int flag = 0;
for (int j = 1; j <= prime_num; j++) {
if (n % prime[j] == 0) {
flag = 1;
least = prime[j];
break;
}
}
if (!flag) {
least = n;
}
long long big_gcd = n / least;
big_lcm = 0;
flag = 0;
if (least == 2) {
printf("%I64d %I64d\n", big_gcd, big_gcd);
return 0;
}
if (least == 3) {
printf("%I64d %I64d\n", big_gcd, big_gcd * 2);
return 0;
}
for (int i = 1; i <= 150; i++) {
for (int j = 0; j <= least; j++) {
dp[i][j] = dp[i - 1][j];
pre[i][j] = j;
int cnt = prime[i];
double t = log(prime[i] * 1.0);
for (int k = 1; cnt <= j; k++) {
double temp = k * t;
if (dp[i][j] < dp[i - 1][j - cnt] + temp) {
pre[i][j] = j - cnt;
dp[i][j] = dp[i - 1][j - cnt] + temp;
}
cnt *= prime[i];
}
}
}
// for (int i = 1; i <= 150; i++) {
// for (int j = 0; j <= least; j++) {
// dp[i][j] = dp[i - 1][j];
// pre[i][j] = j;
// }
// for (int j = prime[i]; j <= least; j *= prime[i]) {
// double temp = log(j * 1.0);
// for (int k = j; k <= least; k++) {
// if (dp[i][k] < dp[i - 1][k - j] + temp) {
// dp[i][k] = dp[i - 1][k - j] + temp;
// pre[i][k] = k - j;
// }
// }
// }
// }
int tot = least;
for (int i = 150; i >= 1; i--) {
if ((tot - pre[i][tot]) != 0) {
printf("%I64d ", (tot - pre[i][tot]) * big_gcd);
tot = pre[i][tot];
}
}
while (tot > 0) {
printf("%I64d ", big_gcd);
tot--;
}
printf("\n");
return 0;
}