UVA 1213 Sum of Different Primes(经典dp)

题意:选择k(k<15)个唯一质数,求出和为n(n<1121)的可能数 

 

题解:预处理dp,dp[k][n]表示使用k个素数拼成n的总方案数

   就是三重枚举,枚举k,枚举n,枚举小于n的素数

   但是注意三重循环的顺序与位置,我们要防重防漏

   第一重循环是枚举每个小于n的素数,思路是对于每个素数放入dp里面的位置

   第二重倒叙枚举每个数n,倒序是类似01背包不能让枚举的素数重复加入同一个dp数组中

   第三重正序枚举个数k只能放在最里面,这样才不会出现重复

 

复制代码
import java.util.Scanner;

public class Main{

    static int Max = 1200;
    static int Maxk = 15;
    static long[][] dp = new long[Maxk][Max];
    static int[] vis = new int[Max];
    static int[] prm = new int[Max];//存所有素数
    static int coun;

    static {
        for (int i = 2; i < Max; ++i) {
            if (vis[i] == 0) {
                for (int j = i + i; j < Max; j += i) {
                    vis[j] = 1;
                }
            }
        }
        for (int i = 2; i < Max; ++i) {
            if (vis[i] == 0) {
                prm[coun++] = i;
            }
        }
    }

    private static void Init(int n) {
        dp[0][0]=1;
        // 预处理dp
        //注意三重循环位置,用于去重
        for (int k = 0; k < coun; ++k) {//枚举每个素数
            for (int j = Max-1; j >=prm[k]; --j) {//倒叙枚举每个数,类似01背包去重
                for (int i = 1; i < Maxk; ++i) {//枚举个数
                        dp[i][j] += dp[i - 1][j - prm[k]];
                }
            }
        }
    }

    public static void main(String[] args) {
        Init(Max);
        int n, k;
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            n = sc.nextInt();
            k = sc.nextInt();
            if (n + k == 0)
                break;
            System.out.println(dp[k][n]);
        }
    }

}
复制代码

 

posted @   专注如一  阅读(602)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
点击右上角即可分享
微信分享提示