[POJ3590]The shuffle Problem (replacement + dp)

Keywords: REST

Title Description

Portal

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]);
    }
}

Posted by Butthead on Tue, 12 Feb 2019 07:21:17 -0800