题目描述
解析
很好的题
记忆化搜索
我一开始的思路就是记忆化搜索
为了不重复,搜索的时候规定拆出来一个数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
*/
但这并不是最好的做法
无限背包
这题可以转化为:
给你一些数(也就是那些质数),然后问你组合成给定数值的方案数
这就是那个硬币方案的题了
用背包可以非常容易的切掉
而且时间复杂度应该比记搜好(记搜的那个复杂度有点玄。。。)
代码
都说到这份上了还要什么代码
(绝对不是我懒得敲)