文章目录
- 题目描述
- 解析
- 记忆化搜索
- 代码
- 无限背包
- 代码
- thanks for reading!
题目描述
解析
很好的题
记忆化搜索
我一开始的思路就是记忆化搜索
为了不重复,搜索的时候规定拆出来一个数A后一会不能再拆比A更小的了
这样就不难写了
(忽略我n^2的素数筛法,反正数据一点点大)
线性筛在这里
代码
#include<bits/stdc++.h>
using namespace std;
const int N=3e6+100;
#define ll long long
int n;
int prime[N],m;
bool sushu(int x){int ans=0;for(int i=1;i<=x;i++){if(x%i==0) ans++;}return ans==2;
}
void solve(){for(int i=2;i<=200;i++){if(sushu(i)) prime[++m]=i;}
}ll dp[250][250];
ll find(int x,int k){if(dp[x][k]) return dp[x][k];if(x==0) return 1;if(x<0||x==1) return 0;ll res=0;for(int j= k;j<=m&&prime[j]<=x;j++){res+=find(x-prime[j],j);}return dp[x][k]=res;
}int main(){solve(); while(scanf("%d",&n)!=EOF){printf("%lld\n",find(n,1));}return 0;
}
/*
12 21 31 40 49 58 69 79 90 101
15
*/
但这并不是最好的做法
无限背包
这题可以转化为:
给你一些数(也就是那些质数),然后问你组合成给定数值的方案数
这就是那个硬币方案的题了
用背包可以非常容易的切掉
而且时间复杂度应该比记搜好(记搜的那个复杂度有点玄。。。)
代码
都说到这份上了还要什么代码
(绝对不是我懒得敲)