题目链接戳这里

题目描述

有\(n\)件不同的商品,每件物品都有无限个,输出总体积为\([1,m]\)的方案数

思路

直接跑背包有\(30\)

考虑把每个物品的生成函数设出来,对于一件体积为\(v\)的物品:

\[f(x)=1+x^v+x^{2v}+\cdots +x^{kv}+\cdots
\]

那么答案\(F(x)\)就是每个物品的\(f\)卷起来:

\[F(x)=\prod\limits_{i=1}^{n}f_i(x)=\prod\limits_{i=1}^{n}\frac{1}{1-x^{v_i}}
\]

直接做是\(O(mnlog\ n)\)的

因为乘法比较麻烦,考虑将其转化为加法,在两边分别取\(ln\)可得:

\[ln\ F(x)=\sum\limits_{i=1}^{n}ln\ f_i(x)
\]

又观察到对\(f(x)\)作如下变化后的形式很特殊,即:

\[ln\ f(x)=\int (ln\ f(x))'=\int \frac{f'(x)}{f(x)}=\int (1-x^v)f'(x)=\int (1-x^v)\sum\limits_{i=1}ivx^{iv-1}=\int \sum\limits_{i=1}ivx^{iv-1}-\sum\limits_{i=2}(i-1)vx^{iv-1}=\int \sum\limits_{i=1}vx^{iv-1}=\sum\limits_{i=1}i^{-1}x^{iv}
\]

竟然是个调和级数的形式,太神奇了!于是\(O(nln\ n)\)地统计一下再做个\(exp\)就行了

#include <cstdio>
#include <algorithm>
#include <cstring> using namespace std; #define N 100000
#define MOD 998244353 int n, m, v[N+5], cnt[N+5];
int f[4 * N + 5], g[4 * N + 5], f1[4 * N + 5], g1[4 * N + 5], h[4 * N + 5]; int fpow(int x, int p)
{
int ret = 1;
while (p)
{
if (p & 1)
ret = 1LL * ret * x % MOD;
x = 1LL * x * x % MOD;
p >>= 1;
}
return ret;
} void bitReverse(int *s, int len, int bit)
{
for (int i = 0; i < len; ++i)
{
int t = 0;
for (int j = 0; j < bit; ++j)
if ((i >> j) & 1)
t |= 1 << (bit - 1 - j);
if (i < t)
swap(s[i], s[t]);
}
} void DFT(int *s, int flag, int len, int bit)
{
bitReverse(s, len, bit);
for (int l = 2; l <= len; l <<= 1)
{
int mid = l >> 1, t = fpow(3, (MOD - 1) / l);
if (flag)
t = fpow(t, MOD - 2);
for (int *p = s; p != s + len; p += l)
{
int w = 1;
for (int i = 0; i < mid; ++i)
{
int x = p[i], y = 1LL * w * p[i + mid] % MOD;
p[i] = (x + y) % MOD, p[i + mid] = (x - y) % MOD;
w = 1LL * w * t % MOD;
}
}
}
if (flag)
{
int inv = fpow(len, MOD - 2);
for (int i = 0; i < len; ++i)
s[i] = 1LL * s[i] * inv % MOD;
}
} void polyInv(int *f, int *g, int c)
{
if (c == 0)
{
g[0] = fpow(f[0], MOD - 2);
return;
}
int len = 1 << c;
polyInv(f, g, c - 1);
for (int i = 0; i < len; ++i)
f1[i] = f[i];
DFT(f1, 0, len << 1, c + 1), DFT(g, 0, len << 1, c + 1);
for (int i = 0; i < (len << 1); ++i)
g[i] = g[i] * (2 - 1LL * f1[i] * g[i] % MOD) % MOD;
DFT(g, 1, len << 1, c + 1);
for (int i = len; i < (len << 1); ++i)
g[i] = 0;
} void d(int *f, int *g, int c)
{
g[c - 1] = 0;
for (int i = 0; i < c - 1; ++i)
g[i] = 1LL * f[i + 1] * (i + 1) % MOD;
} void d_(int *f, int *g, int c)
{
g[0] = 0;
for (int i = 1; i < c; ++i)
g[i] = 1LL * f[i - 1] * fpow(i, MOD - 2) % MOD;
} void polyLn(int *f, int *g, int c)
{
int len = 1 << c;
polyInv(f, g, c);
d(f, g1, len);
DFT(g, 0, len << 1, c + 1), DFT(g1, 0, len << 1, c + 1);
for (int i = 0; i < (len << 1); ++i)
g1[i] = 1LL * g[i] * g1[i] % MOD;
DFT(g1, 1, len << 1, c + 1);
d_(g1, g, len);
for (int i = 0; i < (len << 1); ++i)
f1[i] = g1[i] = 0;
for (int i = len; i < (len << 1); ++i)
g[i] = 0;
} void polyExp(int *f, int *g, int c)
{
if (c == 0)
{
g[0] = 1;
return;
}
int len = 1 << c;
polyExp(f, g, c - 1);
polyLn(g, h, c);
h[0] = (1 - h[0] + f[0]) % MOD;
for (int i = 1; i < len; ++i)
h[i] = (f[i] - h[i]) % MOD;
DFT(g, 0, len << 1, c + 1), DFT(h, 0, len << 1, c + 1);
for (int i = 0; i < (len << 1); ++i)
g[i] = 1LL * g[i] * h[i] % MOD, h[i] = 0;
DFT(g, 1, len << 1, c + 1);
for (int i = len; i < (len << 1); ++i)
g[i] = 0;
} int main()
{
scanf("%d%d", &n, &m);
int bit = 0;
while((1<<bit) < m+1) bit++;
for(int i = 1; i <= n; ++i) {
scanf("%d", &v[i]);
cnt[v[i]]++;
}
for(int i = 1; i <= m; ++i) {
if(!cnt[i]) continue;
for(int j = 1; j*i <= m; ++j)
f[i*j] = (f[i*j]+1LL*cnt[i]*fpow(j, MOD-2))%MOD;
}
polyExp(f, g, bit);
for(int i = 1; i <= m; ++i) printf("%d\n", (g[i]+MOD)%MOD);
return 0;
}

洛谷P4389 付公主的背包--生成函数+多项式的更多相关文章

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

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

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

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

  3. 洛谷 P4389: 付公主的背包

    题目传送门:洛谷 P4389. 题意简述: 有 \(n\) 个物品,每个物品都有无限多,第 \(i\) 个物品的体积为 \(v_i\)(\(v_i\le m\)). 问用这些物品恰好装满容量为 \(i ...

  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. composer windows下安装

    composer windows安装  因要使用PhpSpreadsheet处理excel表格 选择composer安装 1. 下载Composer-Setup.exe 2.点击直接运行---选择ph ...

  2. GridContrl 通用类

    using DevExpress.Data; using DevExpress.Utils; using DevExpress.XtraGrid.Views.Grid; using System; u ...

  3. Golang学习笔记(一)

    这个系列学习文章是对ASTAXIE大神的GoWeb编程的读书笔记. 1. 关于GOPATH $GOPATH 是系统中重要的环境变量,他不是Go的安装目录. 假如我们将GOPATH设置在这里: /hom ...

  4. Dynamics 365-OnPremise V9 安装系统要求

    Dynamics 365 V9 OnPremise发布之后,博主率真地直接下载安装,首先就遇到了操作系统不支持的问题,但是通过CRM安装报错提示,发现给的链接参考信息也不对. document的链接调 ...

  5. Android-蓝牙自动配对与隐藏对话框

    一.概述 本次分析是基于Android7.0的源码. 二.自动配对分析过程 首先,我们分析一下源码的自动配对过程,packages/apps/Settings/src/com/android/sett ...

  6. AndroidStudio使用问题记录

    问题: Gradle sync failed: Connection timed out: connect Consult IDE log for more details (Help | Show ...

  7. IDEA XML注释与取消注释快捷键

    IntelliJ IDEA和eclipse中编辑Java文件时,注释和取消注释的快捷键都是: "CTRL + / " 编辑xml文件时, 注释:CTRL + SHIFT + / 取 ...

  8. row_number() over()分页查询

    1.首先讲下row_number() over() 是干什么的? 是一个分析函数,会在数据表生成一个排序列. 案例SQL: select ROW_NUMBER() over(order by book ...

  9. Greedy分饼干

    分饼干:因为饼干大小和孩子的食欲度不一定是按大小顺序排列的,所以开始要排序一下,然后从最小的饼干依次从食欲小的孩子开始看,如果他愿意吃,就++,看下一个小孩子,这回拿的就是大一点的饼干了. Examp ...

  10. 专业的web打印插件

    Lodop是什么?参考官方网站:http://www.lodop.net/ 有人说她是Web打印控件,因为她能打印.在浏览器中以插件的形式出现,用简单一行语句就把整个网页打印出来: 有人说她是打印编程 ...