把正整数n分成若干个正整数之和的方法数。
http://www.51nod.com/Challenge/Problem.html#problemId=1259
动态规划
答案是g[n]
const int MAXF = 1e3 + 10;
const int MAXG = 2e5 + 10;
int n;
ll f[MAXF], g[MAXG];
void calc() {
f[1] = 1, f[2] = 2, f[3] = 5, f[4] = 7;
for(int i = 5; i < MAXF; ++i)
f[i] = ((3 + 2 * f[i - 2] - f[i - 4]) % MOD + MOD) % MOD;
g[0] = 1;
for(int i = 1; i <= MAXG; ++i) {
for(int j = 1; f[j] <= i; ++j) {
if((j + 1) >> 1 & 1)
g[i] = (g[i] + g[i - f[j]]) % MOD;
else
g[i] = (g[i] - g[i - f[j]] + MOD) % MOD;
}
}
}
\(O(n\sqrt{n})\)
生成函数
\(O(n\log n)\)
易知整数划分的生成函数为
\(F(x)=\prod\limits_{i=1}^{n}\frac{1}{1-x^i}\)
但是这个很难算,看到右边是乘积的形式,考虑两边取对数
\(\ln (F(x))=\ln (\prod\limits_{i=1}^{n}\frac{1}{1-x^i})\)
\(=\sum\limits_{i=1}^{n} \ln\frac{1}{1-x^i}\)
\(=-\sum\limits_{i=1}^{n} \ln(1-x^i)\)
考虑模 \(x^n\) 下的麦克劳林展开
\[\ln(1+x)=\sum\limits_{i=0}^{n}(-1)^{i+1}\frac{x^{n}}{n} \]代入 \(x:=-x^k\)
\(\ln (F(x))=-\sum\limits_{k=1}^{n} \ln(1-x^k)\)
\(=-\sum\limits_{k=1}^{n} \sum\limits_{i=1}^{n}(-1)^{i-1}\frac{(-x^k)^{i}}{i}\)
\(=\sum\limits_{k=1}^{n} \sum\limits_{i=1}^{n}\frac{x^{ki}}{i}\)
\(=\sum\limits_{T=1}^{n} x^T \sum\limits_{k=1}^{n} \sum\limits_{i=1}^{n}\frac{1}{i}[T=ki]\)
\(=\sum\limits_{T=1}^{n} x^T \sum\limits_{k|T} \frac{1}{k}\)
然后再取指数函数即可。
int n;
int A[MAXN], B[MAXN];
int calc(int n) {
fill(B, B + n + 1, 0);
for(int i = 1; i <= n; ++i) {
int invi = qpow(i, MOD - 2);
for(int j = i; j <= n; j += i)
B[j] = qadd(B[j], invi);
}
polyexp(B, n + 1, A);
return A[n];
}
可惜因为对多项式的操作,对模数有一定要求。正常版本是使用FNTT的,不能应对不存在原根的模数(如1e9+7)。
若干个不同正整数之和
http://www.51nod.com/Challenge/Problem.html#problemId=1201