01背包问题
状态:f[i][j]
表示选到第i个数且当前体积是j的方案数
转移方程:
f[i][j]+=f[i-1][j]
不选第i个数
if(j>=prime[i]) f[i][j]+=f[i-1][j-prime[i]]
选第i个数
注意:这i个数只能是质数,所以需要先筛质数.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e4,M=3e3;
typedef long long ll;
int cnt=1,prime[N],st[N];
ll f[M][M];//选了i个物品且体积是j的方案数
int m=2019;
void getprime()
{
for(int i=2;i<2021;i++)
{
if(!st[i]) prime[cnt++]=i;
for(int j=1;j<cnt&&prime[j]*i<2021;j++)
{
st[prime[j]*i]=1;
if((i%prime[j])==0) break;
}
}
}
int main()
{
getprime();
f[0][0]=1;
for(int i=1;i<cnt;i++)
for(int j=0;j<=m;j++)
{
f[i][j]+=f[i-1][j];
if(j>=prime[i]) f[i][j]+=f[i-1][j-prime[i]];
}
cout<<f[cnt-1][m];
return 0;
}