题目链接:

codeforces 27E


题目大意:

给出一个n,问最小的约数个数为n的数是多少。


题目分析:

  • 作为一个懒人,看见这种数打不能取模的就喜欢用java水
  • 首先能够想到为了保证最小,最多也就用到17个质因数,因为这17个质因数的积已经超过了1e8,所以我们可以枚举这17个质因数出现的次数。
  • 然后定义状态dp[i][j]表示前i个质因数组成的因数个数为j个的最小的数。
  • 转移方程很简单: dp[i][j∗k]=min{dp[i−1][j]⋅prime[i]k}
  • 复杂度O(18⋅n2)

AC代码:

import java.math.BigInteger;
import java.util.Scanner;


public class Main {

    static final int MAX = 1007;
    static BigInteger []a =
        {BigInteger.ZERO,BigInteger.valueOf(2),BigInteger.valueOf(3),BigInteger.valueOf(5),
         BigInteger.valueOf(7),BigInteger.valueOf(11),BigInteger.valueOf(13),
         BigInteger.valueOf(17),BigInteger.valueOf(19),BigInteger.valueOf(23),
         BigInteger.valueOf(29),BigInteger.valueOf(31),BigInteger.valueOf(37),
         BigInteger.valueOf(41),BigInteger.valueOf(43),BigInteger.valueOf(47),
         BigInteger.valueOf(53),BigInteger.valueOf(59)};
    static BigInteger [][]pp = new BigInteger[MAX][MAX]; 
    static BigInteger [][]dp = new BigInteger[MAX][MAX];
    static boolean [][]mark = new boolean[MAX][MAX];
    public static void main ( String[] args )
    {
        Scanner cin = new Scanner ( System.in );
        int n;
        for ( int i = 1 ; i < 18 ; i++ )
        {
            pp[i][0] = BigInteger.ONE;
            for ( int j = 1 ; j < MAX ; j++ )
                pp[i][j] = pp[i][j-1].multiply( a[i] );
        }
        while ( cin.hasNext())
        {
            n = cin.nextInt();
            dp[0][1] = BigInteger.ONE;
            for ( int i = 0 ; i < MAX ; i++ )
                for ( int j = 0 ; j < MAX ; j++ )
                    mark[i][j] = false;
            mark[0][1] = true;
            for ( int i = 1 ; i < 18 ; i++ )
                for ( int j = 1 ; j <= n ; j++ )
                {
                    for ( int k = 1; k <= n ; k++ )
                    {
                        if ( j*k > n ) continue;
                        if ( !mark[i-1][j]) continue;
                        if (!mark[i][j*k] || (dp[i-1][j].multiply(pp[i][k-1])).compareTo(dp[i][j*k])< 0 )
                        {
                            dp[i][j*k] = dp[i-1][j].multiply(pp[i][k-1]);
                            mark[i][j*k] = true;
                        }
                    }
                }
            System.out.println(dp[17][n] );
        }
    }

}