题目:
简单错误思路:
dfs:每个状态都需要遍历,所以最坏2 ^ 50 ,TLE
类似于01滚动:考虑到空间存不下就没有实际行动,大概率 MLE
正确答案:
类似于第二种状态,不过是状态压缩,原地滚动,每一步都利用上一步的结果,且用0,1表示状态,节省空间,然后扫一遍判断答案数量即可。
思考:DP真香
#include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<stack> #include<queue> #include<map> #include<list> #include<string> #include<ctype.h> #include<cstring> #include<set> #include<vector> #define ll long long #define mp make_pair #define inf 0x3f3f3f3f #define pb push_back #define PI 3.14159265358979323846 using namespace std; const int maxn = 5e4 + 100; void Fast() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); } int p[maxn] = {0}; int main() { p[0] = p[1] = 1; for(int i = 2;i < maxn;i++){ // 埃氏筛素数 if(!p[i]){ for(int j = i + i ; j < maxn;j += i) p[j] = 1; } } int n; while(~scanf("%d",&n)){ if(n < 0) break; int a[2020];int dp[maxn] = {0}; // dp[i] = 0 表示不能等于 i ,dp[i] = 1 表示可以等于 i int sum = 0; for(int i = 1 ;i <= n;i++) { scanf("%d",&a[i]); sum += a[i]; } dp[0] = 1; for(int i = 1; i <= n;i++){ // 原地滚动DP,我其实没有特别理解,在雨巨的视频里听过 for(int j = sum - a[i];j >= 0;j--){ if(dp[j]) dp[j+a[i]] = 1; } } int ans = 0; for(int i = 2;i <= sum;i++){ if(dp[i] == 1 && p[i] == 0) ans++; } printf("%d ",ans); } }