【LOJ6268】分拆数

news/2024/11/17 9:51:16/

【题目链接】

  • 点击打开链接

【思路要点】

  • 注意到 1 + x + x 2 + x 3 + . . . = 1 1 − x 1+x+x^2+x^3+...=\frac{1}{1-x} 1+x+x2+x3+...=1x1 ,答案 A n s Ans Ans 即为 ∏ i = 1 ∞ 1 1 − x i \prod_{i=1}^{\infty}\frac{1}{1-x^i} i=11xi1 N N N 项的系数,即 A n s ( x ) = ∏ i = 1 ∞ 1 1 − x i Ans(x)=\prod_{i=1}^{\infty}\frac{1}{1-x^i} Ans(x)=i=11xi1
  • 对等式两侧取对数,有
    l n ( A n s ( x ) ) = ∑ i = 1 ∞ l n ( 1 1 − x i ) ln(Ans(x))=\sum_{i=1}^{\infty}ln(\frac{1}{1-x^i}) ln(Ans(x))=i=1ln(1xi1)
  • 注意到由于
    l n ( 1 1 − x i ) = ∑ j = 1 ∞ x i j j ln(\frac{1}{1-x^i})=\sum_{j=1}^{\infty}\frac{x^{ij}}{j} ln(1xi1)=j=1jxij

    l n ( A n s ( x ) ) = ∑ i = 1 ∞ ∑ j = 1 ∞ x i j j ln(Ans(x))=\sum_{i=1}^{\infty}\sum_{j=1}^{\infty}\frac{x^{ij}}{j} ln(Ans(x))=i=1j=1jxij
  • 我们可以在 O ( N L o g N ) O(NLogN) O(NLogN) 的时间内求出 l n ( A n s ( x ) ) ln(Ans(x)) ln(Ans(x)) 的前 N N N 项,再通过多项式 e x p exp exp 得到答案。
  • 时间复杂度 O ( N L o g N ) O(NLogN) O(NLogN)

【代码】

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 5;
const int P = 998244353;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {x = 0; int f = 1;char c = getchar();for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';x *= f;
}
template <typename T> void write(T x) {if (x < 0) x = -x, putchar('-');if (x > 9) write(x / 10);putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {write(x);puts("");
}
namespace Poly {const int MAXN = 262144;const int P = 998244353;const int LOG = 25;const int G = 3;int power(int x, int y) {if (y == 0) return 1;int tmp = power(x, y / 2);if (y % 2 == 0) return 1ll * tmp * tmp % P;else return 1ll * tmp * tmp % P * x % P;}int invn[MAXN], tmpa[MAXN], tmpb[MAXN];int N, Log, home[MAXN]; bool initialized;int forward[MAXN], bckward[MAXN], inv[LOG];void init() {initialized = true;forward[0] = bckward[0] = inv[0] = invn[1] = 1;for (int len = 2, lg = 1; len <= MAXN; len <<= 1, lg++)inv[lg] = power(len, P - 2);for (int i = 2; i < MAXN; i++)invn[i] = (P - 1ll * (P / i) * invn[P % i] % P) % P;int delta = power(G, (P - 1) / MAXN);for (int i = 1; i < MAXN; i++)forward[i] = bckward[MAXN - i] = 1ll * forward[i - 1] * delta % P;}void NTTinit() {for (int i = 0; i < N; i++) {int ans = 0, tmp = i;for (int j = 1; j <= Log; j++) {ans <<= 1;ans += tmp & 1;tmp >>= 1;}home[i] = ans;}}void NTT(int *a, int mode) {assert(initialized);for (int i = 0; i < N; i++)if (home[i] < i) swap(a[i], a[home[i]]);int *g;if (mode == 1) g = forward;else g = bckward;for (int len = 2, lg = 1; len <= N; len <<= 1, lg++) {for (int i = 0; i < N; i += len) {for (int j = i, k = i + len / 2; k < i + len; j++, k++) {int tmp = a[j];int tnp = 1ll * a[k] * g[MAXN / len * (j - i)] % P;a[j] = (tmp + tnp > P) ? (tmp + tnp - P) : (tmp + tnp);a[k] = (tmp - tnp < 0) ? (tmp - tnp + P) : (tmp - tnp);}}}if (mode == -1) {for (int i = 0; i < N; i++)a[i] = 1ll * a[i] * inv[Log] % P;}}void times(vector <int> &a, vector <int> &b, vector <int> &c) {assert(a.size() >= 1), assert(b.size() >= 1);int goal = a.size() + b.size() - 1;N = 1, Log = 0;while (N < goal) {N <<= 1;Log++;}for (int i = 0; i < a.size(); i++)tmpa[i] = a[i];for (int i = a.size(); i < N; i++)tmpa[i] = 0;for (int i = 0; i < b.size(); i++)tmpb[i] = b[i];for (int i = b.size(); i < N; i++)tmpb[i] = 0;NTTinit();NTT(tmpa, 1);NTT(tmpb, 1);for (int i = 0; i < N; i++)tmpa[i] = 1ll * tmpa[i] * tmpb[i] % P;NTT(tmpa, -1);c.resize(goal);for (int i = 0; i < goal; i++)c[i] = tmpa[i];}void timesabb(vector <int> &a, vector <int> &b, vector <int> &c) {assert(a.size() >= 1), assert(b.size() >= 1);int goal = a.size() + b.size() * 2 - 2;N = 1, Log = 0;while (N < goal) {N <<= 1;Log++;}for (int i = 0; i < a.size(); i++)tmpa[i] = a[i];for (int i = a.size(); i < N; i++)tmpa[i] = 0;for (int i = 0; i < b.size(); i++)tmpb[i] = b[i];for (int i = b.size(); i < N; i++)tmpb[i] = 0;NTTinit();NTT(tmpa, 1);NTT(tmpb, 1);for (int i = 0; i < N; i++)tmpa[i] = 1ll * tmpa[i] * tmpb[i] % P * tmpb[i] % P;NTT(tmpa, -1);c.resize(goal);for (int i = 0; i < goal; i++)c[i] = tmpa[i];}void getinv(vector <int> &a, vector <int> &b) {assert(a.size() >= 1), assert(a[0] != 0);b.clear(), b.push_back(power(a[0], P - 2));while (b.size() < a.size()) {vector <int> c, ta = a;ta.resize(b.size() * 2);timesabb(ta, b, c);b.resize(b.size() * 2);for (unsigned i = 0; i < b.size(); i++)b[i] = (2ll * b[i] - c[i] + P) % P;}b.resize(a.size());}void getder(vector <int> &a, vector <int> &b) {assert(a.size() >= 1);if (a.size() == 1) {b.clear();b.resize(1);} else {b.resize(a.size() - 1);for (unsigned i = 0; i < b.size(); i++)b[i] = (i + 1ll) * a[i + 1] % P;}}void getint(vector <int> &a, vector <int> &b) {b.resize(a.size() + 1), b[0] = 0;for (unsigned i = 0; i < a.size(); i++)b[i + 1] = 1ll * invn[i + 1] * a[i] % P;}void getlog(vector <int> &a, vector <int> &b) {assert(a.size() >= 1), assert(a[0] == 1);vector <int> da, inva, db;getder(a, da), getinv(a, inva);times(da, inva, db), getint(db, b);b.resize(a.size());}void getexp(vector <int> &a, vector <int> &b) {assert(a.size() >= 1), assert(a[0] == 0);b.clear(), b.push_back(1);while (b.size() < a.size()) {vector <int> lnb, res;b.resize(b.size() * 2), getlog(b, lnb);for (unsigned i = 0; i < lnb.size(); i++)if (i == 0) lnb[i] = (P + 1 + a[i] - lnb[i]) % P;else if (i < a.size()) lnb[i] = (P + a[i] - lnb[i]) % P;else lnb[i] = (P - lnb[i]) % P;times(lnb, b, res);res.resize(b.size());swap(res, b);}b.resize(a.size());}
}
void update(int &x, int y) {x += y;if (x >= P) x -= P;
}
int main() {Poly :: init();int n; read(n);vector <int> lnres, res;lnres.resize(n + 1);for (int i = 1; i <= n; i++)for (int j = i; j <= n; j += i)update(lnres[j], Poly :: invn[i]);Poly :: getexp(lnres, res);for (int i = 1; i <= n; i++)writeln(res[i]);return 0;
}

http://www.ppmy.cn/news/177062.html

相关文章

loj6268. 分拆数

题意&#xff1a; 求 1 1 1~ n n n的分拆数。 题解&#xff1a; 考虑其生成函数为 F ( x ) ∑ i f ( i ) x i F(x)\sum_if(i)x^i F(x)∑i​f(i)xi 那么 F ( x ) ∏ i 1 1 1 − x i F(x)\prod_{i1}\frac1{1-x^i} F(x)∏i1​1−xi1​ 两边取对数得 ln ⁡ F ( x ) ∑ i 1…

LOJ #6268 分拆数

不会五边形数的菜鸡的分块乱搞 LOJ #6268 题意 求前$ n$个数的整数划分方案数&#xff0c;$ n \leq 10^5$ $ Solution$ 考虑暴力$ DP$ $ f(x,y)$表示放了$ x$个物品总体积为$ y$的方案数 转移分增加一个物品和将前面所有物品的体积均增加$ 1$两种 $ g(x,y)$表示用大小不超过$x$…

loj 6268 分拆数

令 $f_n$ 为将 $n$ 进行分拆的方案数 例如&#xff0c;$411111121322$&#xff0c;则 $f(4) 5$ 求 $f(1) \sim f(n)$ 膜 $998244353$ $n \leq 100000$ sol&#xff1a; 因为 $1xx^2x^3... \frac{1}{1-x}$ 则答案的生成函数为 $\prod \frac{1}{1-x^i}$ 这个东西可以考虑他的 $l…

台式计算机和笔记本电脑的设计架构名称是,笔记本电脑内部结构

笔记本电脑的出现给我们的工作带来了巨大的便利&#xff0c;但鉴于其精密的部件和不菲的价格&#xff0c;相信大多数用户也就从来不敢像对待台式电脑那样将其大卸八块&#xff0c;对它的“内脏”也总有一种神秘感。下面电脑维修知识库就带领大家去探索笔记本电脑内部的奥秘。 笔…

鸿蒙系统笔记本电脑价格,鸿蒙系统笔记本电脑要来了?!

近日&#xff0c;华为在伦敦举办了一场媒体活动&#xff0c;主要介绍了华为鸿蒙系统(HarmonyOS)特性。此外&#xff0c;华为全球高级产品经理 Peter Gauden 还向媒体透露了一些有关鸿蒙系统产品的信息&#xff0c;他表示鸿蒙系统在荣耀智慧屏上首秀之后&#xff0c;未来还会登陆…

鸿蒙系统笔记本电脑价格,鸿蒙系统笔记本电脑要来了?

近日&#xff0c;华为在伦敦举办了一场媒体活动&#xff0c;主要介绍了华为鸿蒙系统(HarmonyOS)特性。此外&#xff0c;华为全球高级产品经理Peter Gauden还向媒体透露了一些有关鸿蒙系统产品的信息&#xff0c;他表示鸿蒙系统在荣耀智慧屏上首秀之后&#xff0c;未来还会登陆海…

计算机专业笔记本电脑华为,适合计算机专业的笔记本电脑有哪些

如果家境好&#xff0c;用得起iPhone&#xff0c;则选Mac&#xff0c;可以学独家的iOS开发&#xff0c;如果不打算学iOS开发或者预算有限&#xff0c;那买PC&#xff0c;配置高打游戏很愉快&#xff0c;可以学前后端开发、Android开发。下面是小编整理的详细内容&#xff0c;一…

如何挑选适合自己的笔记本电脑

因为产品不断推陈出新&#xff0c;硬件更新换代很快&#xff0c;网上介绍的某款产品也只是近期适合&#xff0c;很快就会落后&#xff0c;甚至停产&#xff0c;至于品牌&#xff0c;每个人喜好也不同。所以今天我讲讲选硬件的要求&#xff0c;你对照硬件要求不管什么时候你都能…