质数和分解

 

 思路

首先很显然预处理出200以内的质数表

由于每个数字可以选无数次,可以类比完全背包,最外层枚举当前放哪个质数,内层按照完全背包的顺序枚举,在循环过程中每次按照顺序考虑放哪个质数(放完之后就不再重复考虑,所以自然就是没有重复的)。

一定要注意,初始化 dp[0] = 1,不能初始化成每个dp[prime(表示一个质数)] = 1,因为会重复考虑。

转移的时候由于方案数根据加法原理可得转移:dp[j] += dp[j - prime[i] ]  ;

代码

#include<bits/stdc++.h>
using namespace std;
int prime[105],cnt=1;
int n;
int dp[205];
bool vis[205];
void pre()
{
    prime[1]=2;
    vis[2]=1;
    for(int i=3;i<=201;i++)
    {    
        int sq=sqrt(i),flag=0; 
        for(int j=2;j<=sq;j++)
        {
            if(i%j==0) 
            {
                flag=1;
                break;
            }
        }
        if(!flag) prime[++cnt]=i,vis[i]=1;
    }
}
/*这部分没用
int tr(int p){ int i; for(i=2;i<=p;i++) for(int j=2;j<=p/i;j++) vis[i*j]=1; } int dfs(int now) { if(now==0) return 0; if(dp[now]&&dp[now]!=1) return dp[now]; for(int i=1;i<=cnt&&prime[i]<=now;i++) dp[now]+=dfs(now-prime[i]); return dp[now]; }
*/
int main() { pre(); while(scanf("%d",&n)!=EOF) { memset(dp,0,sizeof(dp)); dp[0]=1; for(int i=1;i<=cnt&&prime[i]<=n;i++) { for(int j=prime[i];j<=n;j++) dp[j]+=dp[j-prime[i]]; } printf("%d\n",dp[n]); } return 0; }

 

posted @ 2021-05-29 17:59  conprour  阅读(404)  评论(0编辑  收藏  举报