[洛谷P4389]付公主的背包
题目大意:有$n(n\leqslant10^5)$种物品,第$i$个物品体积为$v_i$,都有$10^5$件。给定$m(m\leqslant10^5)$,对于$s\in [1,m]$,请你回答用这些商品恰好装$s$体积的方案数
题解:(by Weng_weijie)
背包问题模板(误)
对每个物品构造生成函数$F(x)=\displaystyle\sum_{i=0}^{\infty}x^{vi}=\dfrac{1}{1-x^v}$
然后所有相乘就得到答案(不会乘)
对每个多项式求$\ln$加起来再求$\exp$,但是一个个求也不行(复杂度$O(nm)$),可以记录一下每个$v_i$的出现次数,一次性加起来,这样处理出原式子的复杂度是$O(m\log_2m)$
于是:
$$
\begin{align*}
\ln F(x)&=\int \frac{F'(x)}{F(x)} dx \\\\
&=\int \sum_{i=1}^{\infty}vix^{vi-1}(1-x^v) dx \\\\
&=\int \sum_{i=1}^{\infty}vx^{vi-1} dx\\\\
&=\sum_{i=1}^{\infty}\frac{1}{i}x^{vi}
\end{align*}
$$
然后加起来求$\exp$
卡点:数组开小
C++ Code:
#include <cstdio>
#include <algorithm>
#define maxn 100010
#define N (262144 | 3)
const int mod = 998244353, G = 3;
int n, m;
int inv[N], a[N], b[N];
int num[maxn], maxvi;
namespace Poly {
inline int pw(int base, int p) {
int res = 1;
for (; p; p >>= 1, base = 1ll * base * base % mod) if (p & 1) res = 1ll * res * base % mod;
return res;
}
inline int Inv(int x){return pw(x, mod - 2);}
int lim, ilim, s, rev[N];
int Wn[N];
inline void init(int n) {
lim = 1, s = -1; while (lim < n) lim <<= 1, s++; ilim = inv[lim];
for (int i = 0; i < lim; i++) rev[i] = rev[i >> 1] >> 1 | (i & 1) << s;
int t = pw(G, (mod - 1) / lim);
Wn[0] = 1; for (int i = 1; i <= lim; i++) Wn[i] = 1ll * Wn[i - 1] * t % mod;
}
inline void up(int &a, int b) {if ((a += b) >= mod) a -= mod;}
inline void NTT(int *A, int op = 1) {
for (int i = 0; i < lim; i++) if (i < rev[i]) std::swap(A[i], A[rev[i]]);
for (int mid = 1; mid < lim; mid <<= 1) {
int t = lim / mid >> 1;
for (int i = 0; i < lim; i += mid << 1) {
for (int j = 0; j < mid; j++) {
int W = op ? Wn[t * j] : Wn[lim - t * j];
int X = A[i + j], Y = 1ll * A[i + j + mid] * W % mod;
up(A[i + j], Y), up(A[i + j + mid] = X, mod - Y);
}
}
}
if (!op) for (int i = 0; i < lim; i++) A[i] = 1ll * A[i] * ilim % mod;
}
inline void DER(int *A, int *B, int n) {
B[n - 1] = 0; for (int i = 1; i < n; i++) B[i - 1] = 1ll * A[i] * i % mod;
}
inline void INT(int *A, int *B, int n) {
B[0] = 0; for (int i = 1; i < n; i++) B[i] = 1ll * A[i - 1] * inv[i] % mod;
}
int C[N];
void INV(int *A, int *B, int n) {
if (n == 1) {B[0] = Inv(A[0]); return ;}
INV(A, B, n + 1 >> 1), init(n << 1);
for (int i = 0; i < n; i++) C[i] = A[i];
for (int i = n; i < lim; i++) C[i] = B[i] = 0;
NTT(B), NTT(C);
for (int i = 0; i < lim; i++) B[i] = (2 + mod - 1ll * B[i] * C[i] % mod) * B[i] % mod;
NTT(B, 0);
for (int i = n; i < lim; i++) B[i] = 0;
}
int D[N];
inline void LN(int *A, int *B, int n) {
DER(A, D, n), INV(A, B, n);
init(n << 1);
NTT(B), NTT(D);
for (int i = 0; i < lim; i++) D[i] = 1ll * B[i] * D[i] % mod;
NTT(D, 0), INT(D, B, n);
for (int i = n; i < lim; i++) B[i] = 0;
}
int E[N], F[N];
void EXP(int *A, int *B, int n) {
if (n == 1) {B[0] = 1; return ;}
EXP(A, B, n + 1 >> 1);
for (int i = 0; i < n << 1; i++) E[i] = F[i] = 0;
LN(B, E, n);
for (int i = 0; i < n; i++) F[i] = A[i];
NTT(B), NTT(E), NTT(F);
for (int i = 0; i < lim; i++) B[i] = (1ll + mod - E[i] + F[i]) * B[i] % mod;
NTT(B, 0);
for (int i = n; i < lim; i++) B[i] = 0;
}
}
int main() {
scanf("%d%d", &n, &m); m++;
for (int i = 0, x; i < n; i++) scanf("%d", &x), num[x]++, maxvi = std::max(maxvi, x);
inv[1] = 1; for (int i = 2; i < N; i++) inv[i] = 1ll * inv[mod % i] * (mod - mod / i) % mod;
for (int i = 1; i <= maxvi; i++) {
int tmp = num[i];
if (tmp) {
for (int j = i, x = 1; j < m; j += i, x++) a[j] = (a[j] + 1ll * tmp * inv[x]) % mod;
}
}
Poly::EXP(a, b, m);
for (int i = 1; i < m; i++) printf("%d\n", b[i]);
return 0;
}
[洛谷P4389]付公主的背包的更多相关文章
- 洛谷 P4389 付公主的背包 解题报告
P4389 付公主的背包 题目背景 付公主有一个可爱的背包qwq 题目描述 这个背包最多可以装\(10^5\)大小的东西 付公主有\(n\)种商品,她要准备出摊了 每种商品体积为\(V_i\),都有\ ...
- 洛谷 P4389: 付公主的背包
题目传送门:洛谷 P4389. 题意简述: 有 \(n\) 个物品,每个物品都有无限多,第 \(i\) 个物品的体积为 \(v_i\)(\(v_i\le m\)). 问用这些物品恰好装满容量为 \(i ...
- 洛谷P4389 付公主的背包--生成函数+多项式
题目链接戳这里 题目描述 有\(n\)件不同的商品,每件物品都有无限个,输出总体积为\([1,m]\)的方案数 思路 直接跑背包有\(30\) 考虑把每个物品的生成函数设出来,对于一件体积为\(v\) ...
- 洛谷P4389 付公主的背包 [生成函数,NTT]
传送门 同样是回过头来发现不会做了,要加深一下记忆. 思路 只要听说过生成函数的人相信第一眼都可以想到生成函数. 所以我们要求 \[ ans=\prod \sum_n x^{nV}=\prod \fr ...
- 洛谷 4389 付公主的背包——多项式求ln、exp
题目:https://www.luogu.org/problemnew/show/P4389 关于泰勒展开: https://blog.csdn.net/SoHardToNamed/article/d ...
- luogu P4389 付公主的背包
传送门 神仙题鸭!orz dkw 暴力就是完全背包 而完全背包可以和生成函数扯上关系,记第i种物品质量为\(a_i\),那么这种物品的生成函数\(G(i)=\sum_{j=0}^{\infty}x^{ ...
- P4389 付公主的背包
注意 初始化的时候要这样写 for(int i=1,x;i<=n;i++){ scanf("%d",&x); v[x]++; } for(int i=1;i<= ...
- [洛谷P4388] 付公主的矩形
18.09.09模拟赛T1. 一道数学题. 题目传送门 首先把对角线当成是某个点的移动轨迹,从左下到右上. 那么这个点每上升一个单位长度,就穿过一个格子. 每右移一个单位长度,也会穿过一个格子. 例外 ...
- 洛谷 P2014 选课(树形背包)
洛谷 P2014 选课(树形背包) 思路 题面:洛谷 P2014 如题这种有依赖性的任务可以用一棵树表示,因为一个儿子要访问到就必须先访问到父亲.然后,本来本题所有树是森林(没有共同祖先),但是题中的 ...
随机推荐
- EL 和 JSTL 的使用
EL Express Language 表达式语言 就是把<% 这里可以写java语言 %> 这种jsp的写法简化变为${ }的方式 例如 action="${pageConte ...
- spring-bean(xml方式DI)
三种属性注入方式 构造函数注入 1.在Bean实体中写入构造函数(带参构造) 2. <bean id=”该bean的名称” class=”注入的bean的全路径”> <constru ...
- pycharm界面美化,个人喜欢
进入file-setting选项 界面设置主要是在appearance和editor里面.appearance主要是整个pycharm的主题设置,比如文件管理窗口的颜色,其实就是软件本身的主题设置.我 ...
- openldap完整版本搭建记录
文档信息 目 的:搭建一套完整的OpenLDAP系统,实现账号的统一管理. 1:OpenLDAP服务端的搭建 ...
- 使用 python快速搭建http服务
在 Linux 服务器上或安装了 Python 的机器上,Python自带了一个WEB服务器 SimpleHTTPServer. 我们可以很简单的使用 python -m SimpleHTTPSer ...
- ES6笔记02-箭头函数
eg1:// ES5 匿名函数 var total = values.reduce(function (a, b) { return a + b; }, 0); // ES6 匿名函数 var tot ...
- ethereum(以太坊)(六)--整型(int)
pragma solidity ^0.4.20; /* uint8 uint16 ...uint256 int8 int16 int24 ..int256 uint => uint256 int ...
- .NET领域驱动设计系列(12)
[.NET领域驱动设计实战系列]专题十一:.NET 领域驱动设计实战系列总结 摘要: 一.引用 其实在去年本人已经看过很多关于领域驱动设计的书籍了,包括Microsoft .NET企业级应用框架设计. ...
- 【Effective c++ 读书笔记】条款01 视 C++ 为一个语言联邦
一开始,C++只是 C 加上一些面向对象的特性.C++最初的名称 C with Classes 也反映了这个血缘关系. 但是,现在,当这个语言逐渐成熟,它变得更活跃更无拘束,更大胆冒险,开始接受不同于 ...
- CSS选取指定位置标签first-child、last-child、nth-child
1.first-child 选择列表中的第一个标签. 2.last-child 选择列表中的最后一个标签 3.nth-child(n) 选择列表中的第n个标签 4.nth-child(2n) 选择列表 ...