一道简单题。。。
确实挺简单的,但是这道题把学过的知识点结合的特别好。。。
虽然简单但是还是比较值得去做一下的。。。
给定一个正整数n,求将其分解成若干个素数之和的方案总数。
输入输出格式
输入格式:
一行:一个正整数n
输出格式:
一行:一个整数表示方案总数
输入输出样例
说明
【样例解释】
7=7 7=2+5
7=2+2+3
【福利数据】
【输入】 20
【输出】 26
【数据范围及约定】
对于30%的数据 1<=n<=10
对于100%的数据,1<=n<=10^3
这道题首先我们看到了方案总数,那么显然就是动态规划了。。。
那么这道题怎么做呢?
考虑一下我们分解n所得到的数都是质数,而且可以相等!!!(我就因为这个卡了好久!!!),那么我们就是从小于n的质数表(由于情怀我选择线性筛)中找出若干个数(可以重复),使得它们的相加和等于n。
欸?听着这么耳熟?
无限选取?选与不选?动规?
裸的完全背包啊!!!
所以我们得到动态转移方程:f[j]=f[j]+f[j-c[i]]
还是比较好理解的,我们对于每一个物品都要枚举j,那么我们就要加上之前得到的结果(简单的加法原理)
f[0]=1显然只有全都不取一种情况。。。
最后,附上本题代码:
#include<cstdio> #include<algorithm> #define maxn 1000 #define LL long long using namespace std; LL n,prime[maxn+5],cnt,f[maxn+5]; bool vis[maxn+5]; void pre_fir() { for(int i=2;i<=n;i++) { if(vis[i]==0) { prime[++cnt]=i; } for(int j=1;j<=cnt&&i*prime[j]<=n;j++) { vis[i*prime[j]]=1; if(i%prime[j]==0) { break; } } } } int main() { scanf("%lld",&n); pre_fir(); f[0]=1; for(int i=1;i<=cnt;i++) { for(int j=prime[i];j<=n;j++) { f[j]+=f[j-prime[i]]; } } printf("%lld ",f[n]); return 0; }