P1832 A+B Problem(再升级) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题意:
思路:
一眼背包,把素数筛出来,把每个素数当成一个物品,做一遍完全背包就好了
状态设计:设dp[i][j]为选到第 i 个素数,和恰好 为 j 的方案数
属性:count
状态转移:
决策:选or不选
dp[i][j] = dp[i-1][j] + dp[i][j-a[i]]
小技巧:给数组降维,节约空间(&1)
Code:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mxn=1e3+10,mxv=8e4+10;
int n,len=0,sum=0;
int dp[2][mxv],vis[mxv],prime[mxn];
void init(int n){
for(int i=2;i<=n;i++){
if(!vis[i]) prime[++len]=i,sum+=i;
for(int j=1;prime[j]<=n/i;j++){
vis[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}
}
void solve(){
cin>>n;
init(n);
dp[0][0]=1;
for(int i=1;i<=len;i++){
for(int j=0;j<=sum;j++){
if(j<prime[i]) dp[i&1][j]=dp[(i-1)&1][j];
else dp[i&1][j]=dp[(i-1)&1][j]+dp[i&1][j-prime[i]];
}
}
cout<<dp[len&1][n]<<'\n';
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int __=1;//cin>>__;
while(__--)solve();return 0;
}