luoguP4389 付公主的背包 多项式exp
%%%dkw
话说这是个论文题来着...
考虑生成函数\(OGF\)
对于价值为\(v\)的物品,由于有\(10^5\)的件数,可以看做无限个
那么,其生成函数为\(x^0 + x^{v} + x^{2v} + ... = \frac{1}{1 - x^v}\)
我们所需的答案即\([x^n] \prod \frac{1}{1 - x^{v_i}}\)
只需考虑求出\(A = \prod \frac{1}{1 - x^{v_i}}\)
自然地想到取对数
\(In(A) = \sum In(\frac{1}{1 - x^{v_i}})\)
不难发现
\(In(\frac{1}{1 - x^v}) = - In(1 - x^v)\)
考虑用麦克劳林级数来模拟,那么
由于\(In^{(n)}(1 - x) = - \frac{1}{(1 - x)^n} * (n - 1)!\)
\(-In(1 - x^v) = \sum \frac{x^{vi}}{i}\)
于是,我们可以直接枚举倍数,在\(O(m \log m)\)的时间内完成计算
最后只要\(O(m \log m)\)的\(exp\)一下即可
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ri register int
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
#define drep(io, ed, st) for(ri io = ed; io >= st; io --)
#define gc getchar
inline int read() {
int p = 0, w = 1; char c = gc();
while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
return p * w;
}
const int sid = 500050;
const int mod = 998244353;
int n, m;
int V[sid], F[sid], inv[sid], rev[sid], ans[sid];
inline int Inc(int a, int b) { return (a + b >= mod) ? a + b - mod : a + b; }
inline int Dec(int a, int b) { return (a - b < 0) ? a - b + mod : a - b; }
inline int mul(int a, int b) { return 1ll * a * b % mod; }
inline int fp(int a, int k) {
int ret = 1;
for( ; k; k >>= 1, a = mul(a, a))
if(k & 1) ret = mul(ret, a);
return ret;
}
inline void init(int Maxn, int &n, int &lg) {
n = 1; lg = 0;
while(n < Maxn) n <<= 1, lg ++;
}
inline void NTT(int *a, int n, int opt) {
for(ri i = 0; i < n; i ++) if(i < rev[i]) swap(a[i], a[rev[i]]);
for(ri i = 1; i < n; i <<= 1)
for(ri j = 0, g = fp(3, (mod - 1) / (i << 1)); j < n; j += (i << 1))
for(ri k = j, G = 1; k < i + j; k ++, G = mul(G, g)) {
int x = a[k], y = mul(G, a[i + k]);
a[k] = (x + y >= mod) ? x + y - mod : x + y;
a[i + k] = (x - y < 0) ? x - y + mod : x - y;
}
if(opt == -1) {
int ivn = fp(n, mod - 2);
reverse(a + 1, a + n);
rep(i, 0, n) a[i] = mul(a[i], ivn);
}
}
int ia[sid], ib[sid];
inline void Inv(int *a, int *b, int n) {
if(n == 1) { b[0] = fp(a[0], mod - 2); return; }
Inv(a, b, n >> 1);
int N = 1, lg = 0; init(n + n, N, lg);
for(ri i = 0; i < N; i ++)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (lg - 1));
for(ri i = 0; i < N; i ++) ia[i] = ib[i] = 0;
for(ri i = 0; i < n; i ++) ia[i] = a[i], ib[i] = b[i];
NTT(ia, N, 1); NTT(ib, N, 1);
for(ri i = 0; i < N; i ++)
ia[i] = Dec((ib[i] << 1) % mod, mul(ia[i], mul(ib[i], ib[i])));
NTT(ia, N, -1);
for(ri i = 0; i < n; i ++) b[i] = ia[i];
}
inline void Inv_init(int n) {
inv[0] = inv[1] = 1;
rep(i, 2, n) inv[i] = mul(inv[mod % i], mod - mod / i);
}
inline void wf(int *a, int *b, int n) { for(ri i = 1; i < n; i ++) b[i - 1] = mul(a[i], i); }
inline void jf(int *a, int *b, int n) { for(ri i = 1; i < n; i ++) b[i] = mul(a[i - 1], inv[i]); }
int iv[sid], dx[sid];
inline void In(int *a, int *b, int n) {
for(ri i = 0; i < n + n; i ++) iv[i] = dx[i] = 0;
Inv(a, iv, n); wf(a, dx, n);
int N = 1, lg = 0; init(n + n, N, lg);
for(ri i = 0; i < N; i ++)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (lg - 1));
NTT(iv, N, 1); NTT(dx, N, 1);
for(ri i = 0; i < N; i ++) iv[i] = mul(iv[i], dx[i]);
NTT(iv, N, -1); jf(iv, b, n);
}
int inb[sid], fb[sid];
inline void Exp(int *a, int *b, int n) {
if(n == 1) { b[0] = 1; return; }
Exp(a, b, n >> 1);
for(ri i = 0; i < n + n; i ++) inb[i] = fb[i] = 0;
In(b, inb, n);
int N = 1, lg = 0; init(n + n, N, lg);
for(ri i = 0; i < N; i ++)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (lg - 1));
for(ri i = 0; i < n; i ++) fb[i] = Dec(a[i], inb[i]); fb[0] ++;
for(ri i = 0; i < n; i ++) inb[i] = b[i];
NTT(inb, N, 1); NTT(fb, N, 1);
for(ri i = 0; i < N; i ++) fb[i] = mul(fb[i], inb[i]);
NTT(fb, N, -1);
for(ri i = 0; i < n; i ++) b[i] = fb[i], b[i + n] = 0;
}
inline void calc() {
int N = 1, lg = 0;
init(m + 5, N, lg); Inv_init(N);
for(ri i = 1; i <= m; i ++)
for(ri j = i; j <= m; j += i)
F[j] = Inc(F[j], mul(V[i], inv[j / i]));
Exp(F, ans, N);
rep(i, 1, m) printf("%d\n", ans[i]);
}
int main() {
n = read(); m = read();
rep(i, 1, n) V[read()] ++;
calc();
return 0;
}
luoguP4389 付公主的背包 多项式exp的更多相关文章
- [luogu4389]付公主的背包(多项式exp)
完全背包方案计数问题的FFT优化.首先写成生成函数的形式:对重量为V的背包,它的生成函数为$\sum\limits_{i=0}^{+\infty}x^{Vi}=\frac{1}{1-x^{V}}$于是 ...
- LuoguP4389 付公主的背包【生成函数+多项式exp】
题目背景 付公主有一个可爱的背包qwq 题目描述 这个背包最多可以装10^5105大小的东西 付公主有n种商品,她要准备出摊了 每种商品体积为Vi,都有10^5105件 给定m,对于s\in [1,m ...
- 洛谷 4389 付公主的背包——多项式求ln、exp
题目:https://www.luogu.org/problemnew/show/P4389 关于泰勒展开: https://blog.csdn.net/SoHardToNamed/article/d ...
- luoguP4389 付公主的背包
luogu 显然这是个背包题 显然物品的数量是不用管的 所以考虑大小为\(v\)的物品可以装的体积用生成函数表示一下 \[ f(x)=\sum_{i=0}^{+\infty}x^{vi}=\frac{ ...
- [题解] LuoguP4389 付公主的背包
这个题太神辣- 暴力背包就能获得\(30\)分的好成绩...... \(60\)分不知道咋搞..... 所以直接看\(100\)分吧\(QwQ\) 用一点生成函数的套路,对于一个体积为\(v\)的物品 ...
- 洛谷 P4389 付公主的背包 解题报告
P4389 付公主的背包 题目背景 付公主有一个可爱的背包qwq 题目描述 这个背包最多可以装\(10^5\)大小的东西 付公主有\(n\)种商品,她要准备出摊了 每种商品体积为\(V_i\),都有\ ...
- Luogu4389 付公主的背包(生成函数+多项式exp)
显然构造出生成函数,对体积v的物品,生成函数为1+xv+x2v+……=1/(1-xv).将所有生成函数乘起来得到的多项式即为答案,设为F(x),即F(x)=1/∏(1-xvi).但这个多项式的项数是Σ ...
- 【Luogu4389】付公主的背包
题目 传送门 解法 答案显然是\(n\)个形如\(\sum_{i \geq 1} x^{vi}\)的多项式的卷积 然而直接NTT的时间复杂度是\(O(nm\log n)\) 我们可以把每个多项式求\( ...
- 洛谷P4389 付公主的背包--生成函数+多项式
题目链接戳这里 题目描述 有\(n\)件不同的商品,每件物品都有无限个,输出总体积为\([1,m]\)的方案数 思路 直接跑背包有\(30\) 考虑把每个物品的生成函数设出来,对于一件体积为\(v\) ...
随机推荐
- openstack项目【day23】:openstack组件介绍
本节内容 openstack介绍 openstack项目(服务名是项目名的别名) openstack运行流程 openstack各组件详解 一:openstack介绍 open ...
- jeecms常用的标签
友情链接 <dt>友情链接:</dt> [@cms_friendlink_list] [#list tag_list as link] <dd><a href ...
- MongoDB探索之路(二)——系统设计之CRUD
1.构造实体类 using System; using System.Collections.Generic; using System.Linq; using System.Text; using ...
- javascript命名空间
命名空间:命名空间有助于减少程序中所需要的全局变量的数量,并且同时还有助于避免命名冲突或过长的名字前缀. 板栗: var MYAPP = MYAPP || {}; MYAPP.namespace = ...
- python 入门基础22 --复习 面向对象
面向过程编程思想: 核心:过程 过程指的是解决问题的具体步骤,即先干什么再干什么. 基于该编程思想编写程序,相当于一条流水线,一种机械式的思维方式. 面向对象编程思想: 核心:对象 对象指的是数据与方 ...
- Jenkins的安装及使用(二)
介绍两个方面:编译本地项目和拉取git代码并编译 在这之前,先要进行一个配置. 一.编译本地项目 开始添加任务,任务类型选择自由风格: 点击项目进入详情,源码管理选择无 在构建的地方选择项目,然后注意 ...
- 恶意代码分析实战-确认EXE什么时候编译的
场景 确认开源的后门在中毒机器上是什么版本,具有什么功能. 思路 1.查看样本PE里的编译时间 2.对照开源后门里组件的编译时间 技术点 查看NT头-TimeDateStamp struct IMAG ...
- 基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集【转】
转自:http://www.cnblogs.com/surpassal/archive/2012/12/19/zed_webcam_lab1.html 一直想把USB摄像头接到Zedboard上,搭建 ...
- Entity Framework 6.1.0 Tools for Visual Studio 2012 & 2013
http://www.microsoft.com/en-us/download/confirmation.aspx?id=40762
- nio--自己总结
阻塞/非阻塞 + 同步/异步 其实,这两者存在本质的区别,面向的对象是不同的. 阻塞/非阻塞:进程/线程需要操作的数据如果尚未就绪,是否妨碍了当前进程/线程的后续操作. 同步/异步:数据如果尚未就 ...