codeforces 27E E. Number With The Given Amount Of Divisors(dp+数论)

题目链接:

codeforces 27E


题目大意:

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


题目分析:

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

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

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值