题目传送门:洛谷 P4389

题意简述:

有 \(n\) 个物品,每个物品都有无限多,第 \(i\) 个物品的体积为 \(v_i\)(\(v_i\le m\))。

问用这些物品恰好装满容量为 \(i\) 的背包的方案数,两个方案不同当且仅当存在某一个物品的选取数量不同。

你需要对 \(i\in [1,m]\) 回答,答案对 \(998,244,353\) 取模。

题解:

对于一个体积为 \(v\) 的物品,它装满容量为 \(x\) 的背包的方案数序列为 \(a_x=[v|x]\)。

例如 \(v=3\) 时有序列(从 \(0\) 开始):\(\{1,0,0,1,0,0,1,0,0,1,0,\cdots\}\)。

它的普通生成函数为 \(\displaystyle\frac{1}{1-x^v}\)。

记答案的普通生成函数为 \(F(x)\),则有 \(\displaystyle F(x)=\prod_{i=1}^{n}\frac{1}{1-x^{v_i}}\)。

两边取对数:\(\displaystyle\ln F(x)=\sum_{i=1}^{n}\ln\frac{1}{1-x^{v_i}}\)。

有一个式子:\(\displaystyle\ln\frac{1}{1-x^k}=\sum_{i=1}^{\infty}\frac{1}{i}x^{ik}\)。

这个式子的证明:

记 \(\displaystyle F(x)=\frac{1}{1-x^k}\),设 \(G(x)=\ln F(x)\)。

\[\begin{aligned}G(x)&=\ln F(x)\\&=\int(\frac{\mathrm{d}}{\mathrm{d}x}\ln F)(x)\mathrm{d}x\\&=\int(\frac{F'(x)}{F(x)})\mathrm{d}x\\&=\int((1-x^k)F'(x))\mathrm{d}x\\&=\int((1-x^k)\sum_{i=1}^{\infty}k\cdot i\cdot x^{ki-1})\mathrm{d}x\\&=\int(\sum_{i=1}^{\infty}k\cdot i\cdot x^{ki-1}-\sum_{i=1}^{\infty}k\cdot i\cdot x^{ki-1}\cdot x^k)\mathrm{d}x\\&=\int(\sum_{i=1}^{\infty}k\cdot i\cdot x^{ki-1}-\sum_{i=1}^{\infty}k\cdot (i-1)\cdot x^{ki-1})\mathrm{d}x\\&=\int(\sum_{i=1}^{\infty}k\cdot x^{ki-1})\mathrm{d}x\\&=\sum_{i=1}^{\infty}\frac{1}{i}x^{ki}\end{aligned}
\]

建议背一些常用式子。

那么就显而易见了:

\[\begin{aligned}\ln F(x)&=\sum_{i=1}^{n}\sum_{j=1}^{\infty}\frac{1}{j}x^{v_{i}j}\\&=\sum_{k=1}^{m}\sum_{j=1}^{\infty}\frac{\displaystyle\sum_{i=1}^{n}[v_i=k]}{i}x^{kj}\end{aligned}
\]

记 \(b_k\) 为体积为 \(k\) 的物品数量,并且我们只需要次数小于等于 \(m\) 的项,有 \(\displaystyle\ln F(x)\equiv\sum_{k=1}^{m}\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}\frac{b_k}{i}x^{kj}\pmod{x^{m+1}}\)。

右边可以在 \(\displaystyle\sum_{i=1}^{m}\frac{m}{i}=O(m\ln m)\) 的时间内得到,左边使用多项式 \(\mathrm{Exp}\) 在 \(O(m\log m)\) 的时间内得到,总时间复杂度 \(O(m\log m)\)。

#include <cstdio>
#include <cstring>
#include <algorithm> typedef long long LL;
const int Mod = 998244353;
const int G = 3, iG = 332748118;
const int MS = 1 << 19 | 7; inline LL qPow(LL b, int e) {
LL a = 1;
for (; e; e >>= 1, b = b * b % Mod)
if (e & 1) a = a * b % Mod;
return a;
} LL Inv[MS]; inline void Init(int N) {
Inv[1] = 1;
for (int i = 2; i < N; ++i) Inv[i] = -(Mod / i) * Inv[Mod % i] % Mod;
} int Sz, R[MS]; LL InvSz; inline void InitFNTT(int N) {
int Bt = 0;
for (; 1 << Bt < N; ++Bt) ;
if (Sz == (1 << Bt)) return ;
Sz = 1 << Bt; InvSz = -(Mod - 1) / Sz;
for (int i = 1; i < Sz; ++i) R[i] = R[i >> 1] >> 1 | (i & 1) << (Bt - 1);
} inline void FNTT(LL *A, int Ty) {
for (int i = 0; i < Sz; ++i) if (R[i] < i) std::swap(A[R[i]], A[i]);
for (int j = 1, j2 = 2; j < Sz; j <<= 1, j2 <<= 1) {
LL gn = qPow(~Ty ? G : iG, (Mod - 1) / j2), g, X, Y;
for (int i = 0, k; i < Sz; i += j2) {
for (k = 0, g = 1; k < j; ++k, g = g * gn % Mod) {
X = A[i + k], Y = g * A[i + j + k] % Mod;
A[i + k] = (X + Y) % Mod, A[i + j + k] = (X - Y) % Mod;
}
}
}
if (!~Ty) for (int i = 0; i < Sz; ++i) A[i] = A[i] * InvSz % Mod;
} inline void PolyInv(LL *A, int N, LL *B) {
static LL tA[MS], tB[MS];
B[0] = qPow(A[0], Mod - 2);
for (int L = 1; L < N; L <<= 1) {
int L2 = L << 1, L4 = L << 2;
InitFNTT(L4);
memcpy(tA, A, 8 * L2);
memset(tA + L2, 0, 8 * (Sz - L2));
memcpy(tB, B, 8 * L);
memset(tB + L, 0, 8 * (Sz - L));
FNTT(tA, 1), FNTT(tB, 1);
for (int i = 0; i < Sz; ++i) tB[i] = (2 - tB[i] * tA[i]) % Mod * tB[i] % Mod;
FNTT(tB, -1);
for (int i = 0; i < L2; ++i) B[i] = tB[i];
}
} inline void PolyLn(LL *A, int N, LL *B) {
static LL tA[MS], tB[MS];
PolyInv(A, N - 1, tB);
InitFNTT(N * 2 - 3);
for (int i = 1; i < N; ++i) tA[i - 1] = i * A[i] % Mod;
memset(tA + N - 1, 0, 8 * (Sz - N + 1));
memset(tB + N - 1, 0, 8 * (Sz - N + 1));
FNTT(tA, 1), FNTT(tB, 1);
for (int i = 0; i < Sz; ++i) tA[i] = tA[i] * tB[i] % Mod;
FNTT(tA, -1);
B[0] = 0;
for (int i = 1; i < N; ++i) B[i] = tA[i - 1] * Inv[i] % Mod;
} inline void PolyExp(LL *A, int N, LL *B) {
static LL tA[MS], tB[MS];
B[0] = 1;
for (int L = 1; L < N; L <<= 1) {
int L2 = L << 1, L4 = L << 2;
memset(B + L, 0, 8 * (L2 - L));
PolyLn(B, L2, tB);
InitFNTT(L4);
memcpy(tA, B, 8 * L);
memset(tA + L, 0, 8 * (Sz - L));
for (int i = 0; i < L2; ++i) tB[i] = ((!i) - tB[i] + A[i]) % Mod;
memset(tB + L2, 0, 8 * (Sz - L2));
FNTT(tA, 1), FNTT(tB, 1);
for (int i = 0; i < Sz; ++i) tA[i] = tA[i] * tB[i] % Mod;
FNTT(tA, -1);
for (int i = 0; i < L2; ++i) B[i] = tA[i];
}
} int N, M;
int buk[MS];
LL A[MS], B[MS]; int main() {
scanf("%d%d", &N, &M);
Init(MS);
for (int i = 1, v; i <= N; ++i) scanf("%d", &v), ++buk[v];
for (int i = 1; i <= M; ++i) if (buk[i]) {
for (int j = 1; j <= M / i; ++j) {
A[i * j] = (A[i * j] + buk[i] * Inv[j]) % Mod;
}
}
PolyExp(A, M + 1, B);
for (int i = 1; i <= M; ++i) printf("%lld\n", (B[i] + Mod) % Mod);
return 0;
}

洛谷 P4389: 付公主的背包的更多相关文章

  1. 洛谷 P4389 付公主的背包 解题报告

    P4389 付公主的背包 题目背景 付公主有一个可爱的背包qwq 题目描述 这个背包最多可以装\(10^5\)大小的东西 付公主有\(n\)种商品,她要准备出摊了 每种商品体积为\(V_i\),都有\ ...

  2. 洛谷P4389 付公主的背包--生成函数+多项式

    题目链接戳这里 题目描述 有\(n\)件不同的商品,每件物品都有无限个,输出总体积为\([1,m]\)的方案数 思路 直接跑背包有\(30\) 考虑把每个物品的生成函数设出来,对于一件体积为\(v\) ...

  3. 洛谷P4389 付公主的背包 [生成函数,NTT]

    传送门 同样是回过头来发现不会做了,要加深一下记忆. 思路 只要听说过生成函数的人相信第一眼都可以想到生成函数. 所以我们要求 \[ ans=\prod \sum_n x^{nV}=\prod \fr ...

  4. [洛谷P4389]付公主的背包

    题目大意:有$n(n\leqslant10^5)$种物品,第$i$个物品体积为$v_i$,都有$10^5$件.给定$m(m\leqslant10^5)$,对于$s\in [1,m]$,请你回答用这些商 ...

  5. 洛谷 4389 付公主的背包——多项式求ln、exp

    题目:https://www.luogu.org/problemnew/show/P4389 关于泰勒展开: https://blog.csdn.net/SoHardToNamed/article/d ...

  6. luogu P4389 付公主的背包

    传送门 神仙题鸭!orz dkw 暴力就是完全背包 而完全背包可以和生成函数扯上关系,记第i种物品质量为\(a_i\),那么这种物品的生成函数\(G(i)=\sum_{j=0}^{\infty}x^{ ...

  7. P4389 付公主的背包

    注意 初始化的时候要这样写 for(int i=1,x;i<=n;i++){ scanf("%d",&x); v[x]++; } for(int i=1;i<= ...

  8. [洛谷P4388] 付公主的矩形

    18.09.09模拟赛T1. 一道数学题. 题目传送门 首先把对角线当成是某个点的移动轨迹,从左下到右上. 那么这个点每上升一个单位长度,就穿过一个格子. 每右移一个单位长度,也会穿过一个格子. 例外 ...

  9. 洛谷 P2014 选课(树形背包)

    洛谷 P2014 选课(树形背包) 思路 题面:洛谷 P2014 如题这种有依赖性的任务可以用一棵树表示,因为一个儿子要访问到就必须先访问到父亲.然后,本来本题所有树是森林(没有共同祖先),但是题中的 ...

随机推荐

  1. 从C简单程序的汇编代码入手,以理解计算机工作原理。

    贺邦  原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000#/info 知识准备 ...

  2. JDBC学习笔记——PreparedStatement的使用

    PreparedStatement public interface PreparedStatement extends Statement;可以看到PreparedStatement是Stateme ...

  3. 暑假学习笔记(一)——初识Neo4j和APICloud入门

    暑假学习笔记(一)--初识Neo4j和APICloud入门 20180719笔记 1.Neo4j 接了学姐的系统测试报告任务,感觉工作很繁重,但是自己却每天挥霍时光.9月份就要提交系统测试报告了,但是 ...

  4. PAT 1048 数字加密

    https://pintia.cn/problem-sets/994805260223102976/problems/994805276438282240 本题要求实现一种数字加密方法.首先固定一个加 ...

  5. Git从零开始(三)

    一.远程仓库管理 1.将本地内容推送到远程库 先关联远程库,执行命令: git remote add origin https://github.com/Hollydan/gitstore.git ( ...

  6. poj2559 Largest Rectangle in a Histogram(单调栈)

    Description A histogram is a polygon composed of a sequence of rectangles aligned at a common base l ...

  7. java 枚举 封装操作方法

    前言: 由于刚转java项目,所以对于java语言比较陌生,尤其是lambda和一些诸如(一个java文件只能有一个public class)等等的零散知识点之类... 使我觉得就语言的层级来说..n ...

  8. MT【177】三个乘积和

    对任意 2 个 1,2,3,4,5,6 的全排列 $(a_1,a_2,a_3,a_4,a_5,a_6)$ 和 $(b_1,b_2,b_3,b_4,b_5,b_6)$,求$\displaystyle S ...

  9. BZOJ 4764: 弹飞大爷

    4764: 弹飞大爷 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 4  Solved: 4[Submit][Status][Discuss] Des ...

  10. (转)JDK工具-javadoc命令

    背景:最近在学习java基础知识,看到文档注释部分,一种是在dos命令下生成api文件,另一种是在eclipse下生成api文件.dos方式在<疯狂java讲义>中有详细的说明,eclip ...