洛谷P2563 [AHOI2001]质数和分解
题目描述
任何大于 1 的自然数 n 都可以写成若干个大于等于 2 且小于等于 n 的质数之和表达式(包括只有一个数构成的和表达式的情况),并且可能有不止一种质数和的形式。例如,9 的质数和表达式就有四种本质不同的形式:
9 = 2 + 5 + 2 = 2 + 3 + 2 + 2 = 3 + 3 + 3 = 2 + 7 。
这里所谓两个本质相同的表达式是指可以通过交换其中一个表达式中参加和运算的各个数的位置而直接得到另一个表达式。
试编程求解自然数 n 可以写成多少种本质不同的质数和表达式。
输入输出格式
输入格式:
文件中的每一行存放一个自然数 n(2 < n < 200) 。
输出格式:
依次输出每一个自然数 n 的本质不同的质数和表达式的数目。
输入输出样例
输出样例#1:
1
9845164
分析:虽然可以用dp给秒掉,但这道题还可以用来练习一下母函数.构造如下的母函数:G(x) = (1 + x^2 + x^4 + x^6+......) * (1 + x^3 + x^6 + x^9 +......) * (1 + x^5 + x^10 + x^15 + ......) * ......
套用模板,看一下对应次数的系数是多少就可以了.
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; bool vis[2100]; int prime[2100], tot, n, ans[2100]; void init() { for (int i = 2; i <= 200; i++) { if (!vis[i]) prime[++tot] = i; for (int j = 1; j <= tot; j++) { int t = prime[j] * i; if (t > 200) break; vis[t] = 1; if (i % prime[j] == 0) break; } } } int main() { init(); ans[0] = 1; for (int i = 1; i <= tot; i++) for (int j = 200; j >= 0; j--) if (ans[j]) for (int k = prime[i]; k + j <= 200; k += prime[i]) ans[k + j] += ans[j]; while (scanf("%d",&n) != EOF) printf("%d\n", ans[n]); return 0; }