题目:
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
将 2019 拆分为若干个两两不同的质数之和,一共有多少种不同的方法?
注意交换顺序视为同一种方法,例如 2+2017=2019 与2017+2=2019 视为同一种方法。
运行限制
- 最大运行时间:1s
- 最大运行内存: 128M
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
static int n=2500;
static int[]arr=new int[n]; //存放质数
static long dp[][]=new long[n][n]; //记录方案数
public static void main(String[] args) {
int cur=1;
for(int i=2;i<2019;i++){
if(ispre(i)) { //判断是否为质数进行存储
arr[cur++]=i;
}
}
dp[0][0]=1;
for(int i=1;i<cur;i++){
for(int j=0;j<=2019;j++){
dp[i][j]=dp[i-1][j];
if(arr[i]<=j){
dp[i][j]+=dp[i-1][j-arr[i]]; //利用状态转移方程进行求解
}
}
}
System.out.println(dp[cur-1][2019]);
}
public static boolean ispre(int n){
for(int i=2;i<=Math.sqrt(n);i++){
if(n%i==0){
return false;
}
}
return true;
} //判断是否是质数
}
思路:本题采用动态规划,先将<=2019的质数存储到arr数组中。
dp[i][j]的含义是前i个质数组成j有几种方法我们在统计dp[i][j]时如果j<arr[i]那么就说明j无法分解为arr[i]和另一个质数的和,那么dp[i][j]=dp[i-1][j],因为前i个质数肯定包含了前i-1个质数。相反如果j>=arr[i]则dp[i][j]除了等于dp[i-1][j]外还要加上dp[i-1][j-arr[i]],因为如果质数可以组成j-arr[i]则加上arr[i]也可以组成j。获得状态转移方程:
dp[i][j]=dp[i-1][j];
和
dp[i][j]=dp[i-1][j]+dp[i-1][j-arr[i]];
利用这两个状态方程解题。
注:2019可以由多个质数组合而成不是必须两个。