背包题的大特征:题目中某些参数(所有物品体积)相加<=一个不变的参数(背包体积)
题目(2019蓝桥国赛B题):2019可以被分解成若干个两两不同的素数,请问不同的分解方案有多少种?
注意:分解方案不考虑顺序,如2+2017=2019和2017+2=2019属于同一种方案。
背包题的大特征:题目中有一个参数不变,即背包(最大)体积不变,且要某些参数相加<=这个参数(体积) 先定(看是否符合)大特征,确定是背包题,再定(看是否符合)小特征,确定是哪种背包 装箱题:物品没有权值,只有体积,且体积相加是否等于某个固定值(即是否能装满某个空间) 01背包题:物品有权值,有体积 二维背包:题目中还有一个参数不变,即背包(最大)承重不变,且要某些参数相加<=这个参数(重量)。且物品有权值,有体积有重量 分组背包:同组物品互斥(每组物品最多只能拿一个) 先找出小于2019的所有素数 发现题目要我们拼凑素数,且和要为2019, 即题目有一个参数不变(2019),且素数相加要等于2019,所以为背包题 因为物品只有一个参数,且相加的体积要等于固定值(2019),所以是装箱题 求的是方案数即装满2019的方案数 转移方程:if(f[ j-v[i] ]) f[j]+=f[j-v[i]]; 题目中的两两不同表示每个物品只能放一次 做题要会将题转化为某个模型
//
#include<bits/stdc++.h> using namespace std; #define ll long long int const N=5e3+7; int n,m; int z[N]; //欧拉筛的v[i],i的最小质因子 int v[N]; //体积 //质数表 ll f[N]; int main(){ m=2019; //以下是欧拉筛 for(int i=2;i<=2019;++i){ if(z[i]==0){ z[i]=i; v[++n]=i; } for(int j=1;j<=n;++j){ if( v[j]>z[i] || i*v[j]>2019 ) break; z[ i*v[j] ] = v[j]; } } //以下是装箱 f[0]=1; for(int i=1;i<=n;++i){ for(int j=m;j>=v[i];--j){ if(f[j-v[i]]) f[j]+=f[j-v[i]]; } } cout << f[m]; return 0; }