题目链接
完全背包模型 :看到组成大数n小质数可以选无数次
过河卒模型:到达某点的方案数。
状态:dp[
i
i
i][
j
j
j] 考虑前
i
i
i个质数,组成
j
j
j的方案数;
转移过程就参照完全背包结合过河卒:
d
p
[
j
]
=
d
p
[
j
]
+
d
p
[
j
−
a
[
[
i
]
]
dp[j]=dp[j]+dp[j-a[[i]]
dp[j]=dp[j]+dp[j−a[[i]]
d
p
[
j
]
dp[j]
dp[j]:第i个质数不选直接继承,
d
p
[
j
−
a
[
i
]
]
dp[j-a[i]]
dp[j−a[i]]第i个物品选,方案为所有组成
j
−
a
[
i
]
j-a[i]
j−a[i]的后外加一个
a
[
i
]
a[i]
a[i]
for(int i=1;i<=cnt;i++){
for(int j=a[i];j<=n;j++){
dp[j]+=dp[j-a[i]];
}
}
当然 a [ i ] a[i] a[i]不是白给的,利用埃氏筛提前找出素数
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define RG register int
#define ULL unsigned long long
const int INF=2147483647;
LL dp[1010];
int a[1010];
bool f[1010];
int susu(int x){
memset(f,1,sizeof(f));
f[1]=0;
for(int i=2;i<=x;i++){
if(f[i]){
for(int j=i*2;j<=x;j+=i)f[j]=0;
}
}
int cnt=1;
for(int i=1;i<=x;i++){
if(f[i])a[cnt++]=i;
}
return cnt-1;
}
int main()
{
int n;
dp[0]=1;
cin>>n;
int cnt=susu(n);
for(int i=1;i<=cnt;i++){
for(int j=a[i];j<=n;j++){
dp[j]+=dp[j-a[i]];
}
}
cout<<dp[n];
return 0;
}