Title Description
Title Solution
This question is very similar to BZOJ1025, but this requirement is changed the most times, that is, lcm is the largest.
So dp
After the prime number (group) is preprocessed, f(i,j) denotes the maximum product of group I and J.
Then record the solution, and then recurse back.
Because the dictionary order is the smallest, all the first 1 will remain unchanged, and then the selected prime number (power) will be sorted from small to large, each cycle section will move the first to the back and then the rest will be pushed forward.
Code
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 105
int T,n,ans,ansi,ansj;
int p[N],prime[N],bag[N][20],cnt[N],num[N],a[N];
struct data
{
int val,prei,prej,ch;
}f[N][N];
void get_p()
{
for (int i=2;i<=100;++i)
{
if (!p[i]) prime[++prime[0]]=i;
for (int j=1;j<=prime[0]&&i*prime[j]<=100;++j)
{
p[i*prime[j]]=1;
if (i%prime[j]==0) break;
}
}
for (int i=1;i<=prime[0];++i)
{
bag[i][cnt[i]=1]=prime[i];
int now=prime[i];
while (now*prime[i]<=100)
{
now*=prime[i];
bag[i][++cnt[i]]=now;
}
}
}
void calc(int i,int j)
{
if (f[i][j].ch) num[++num[0]]=f[i][j].ch;
if (f[i][j].prei&&f[i][j].prej) calc(f[i][j].prei,f[i][j].prej);
}
int main()
{
get_p();
scanf("%d",&T);
while (T--)
{
scanf("%d",&n);
memset(f,0,sizeof(f));
for (int i=0;i<=n;++i) f[i][0].val=1;
for (int i=1;i<=prime[0];++i)
for (int j=0;j<=n;++j)
{
f[i][j].val=f[i-1][j].val;
f[i][j].prei=i-1,f[i][j].prej=j;
f[i][j].ch=0;
for (int k=1;k<=cnt[i];++k)
if (j>=bag[i][k])
{
if (f[i-1][j-bag[i][k]].val*bag[i][k]>f[i][j].val)
{
f[i][j].val=f[i-1][j-bag[i][k]].val*bag[i][k];
f[i][j].prei=i-1,f[i][j].prej=j-bag[i][k];
f[i][j].ch=bag[i][k];
}
}
else break;
}
ans=0;
for (int i=1;i<=prime[0];++i)
for (int j=0;j<=n;++j)
if (f[i][j].val>ans)
{
ans=f[i][j].val;
ansi=i,ansj=j;
}
num[0]=0;
calc(ansi,ansj);
sort(num+1,num+num[0]+1);
int sum=n;
for (int i=1;i<=num[0];++i) sum-=num[i];
for (int i=1;i<=n;++i) a[i]=i;
int now=sum+1;
for (int i=1;i<=num[0];++i)
{
for (int j=now;j<now+num[i]-1;++j)
a[j]=j+1;
a[now+num[i]-1]=now;
now+=num[i];
}
printf("%d ",ans);
for (int i=1;i<=n;++i) printf("%d%c",a[i]," \n"[i==n]);
}
}