LuoguP4389 付公主的背包【生成函数+多项式exp】
题目背景
付公主有一个可爱的背包qwq
题目描述
这个背包最多可以装10^5105大小的东西
付公主有n种商品,她要准备出摊了
每种商品体积为Vi,都有10^5105件
给定m,对于s\in [1,m]s∈[1,m],请你回答用这些商品恰好装s体积的方案数
输入输出格式
输入格式:
第一行n,m
第二行V1~Vn
输出格式:
m行,第i行代表s=i时方案数,对998244353取模
输入输出样例
输入样例#1:
2 4
1 2
输出样例#1:
1
2
2
3
说明
对于30%的数据,n<=3000,m<=3000
对于60%的数据,纯随机生成
对于100%的数据, n<=100000,m<=100000
对于100%的数据,Vi<=m
思路
首先我们得到这道题是n个形如\(\sum_{i=0}^{\infin}x^{vi}\)的生成函数的乘积,然后考虑优化
因为这里个数的上限是\(1e5\)可以看做无限大
所以我们可以得到
\]
然后因为直接多项式相乘非常麻烦
考虑取ln之后相加
\]
求一波导数
\]
然后把\((1-x^v)\)展开变成
\]
所以
\]
这样的话多项式的有效项数和是一个调和级数
所以多项式加\(\O(n\log n)\)
然后exp回去
#include<bits/stdc++.h>
using namespace std;
int read() {
int res = 0; char c = getchar();
while (!isdigit(c)) c = getchar();
while (isdigit(c)) res = (res << 1) + (res << 3) + c - '0', c = getchar();
return res;
}
typedef long long ll;
typedef vector<int> Poly;
const int N = 3e5 + 10;
const int Mod = 998244353;
const int G = 3;
int add(int a, int b, int mod = Mod) {
return (a += b) >= mod ? a - mod : a;
}
int sub(int a, int b, int mod = Mod) {
return (a -= b) < 0 ? a + mod : a;
}
int mul(int a, int b, int mod = Mod) {
return 1ll * a * b % mod;
}
int fast_pow(int a, int b, int mod = Mod) {
int res = 1;
for (; b; b >>= 1, a = mul(a, a, mod))
if (b & 1) res = mul(res, a, mod);
return res;
}
int w[2][N];
void init() {
int wn;
for (int i = 1; i < (1 << 18); i <<= 1) {
w[1][i] = w[0][i] = 1;
wn = fast_pow(G, (Mod - 1) / (i << 1));
for (int j = 1; j < i; j++)
w[1][i + j] = mul(wn, w[1][i + j - 1]);
wn = fast_pow(G, Mod - 1 - (Mod - 1) / (i << 1));
for (int j = 1; j < i; j++)
w[0][i + j] = mul(wn, w[0][i + j - 1]);
}
}
void transform(int *t, int len, int typ) {
for (int i = 0, j = 0, k; j < len; j++) {
if (j > i) swap(t[i], t[j]);
for (k = (len >> 1); k & i; k >>= 1) i ^= k;
i ^= k;
}
for (int i = 1; i < len; i <<= 1) {
for (int j = 0; j < len; j += (i << 1)) {
for (int k = 0; k < i; k++) {
int x = t[j + k], y = mul(w[typ][i + k], t[i + j + k]);
t[j + k] = add(x, y);
t[j + k + i] = sub(x, y);
}
}
}
if (typ) return;
int inv = fast_pow(len, Mod - 2);
for (int i = 0; i < len; i++)
t[i] = mul(t[i], inv);
}
void print(Poly a) {
for (size_t i = 0; i < a.size(); i++) {
cout<<a[i]<<" ";
}cout<<endl;
}
void clean(Poly &a) {
while (a.size() && !a.back())
a.pop_back();
}
Poly add(Poly a, Poly b) {
a.resize(max(a.size(), b.size()));
for (size_t i = 0; i < b.size(); i++)
a[i] = add(a[i], b[i]);
return a;
}
Poly sub(Poly a, Poly b) {
a.resize(max(a.size(), b.size()));
for (size_t i = 0; i < b.size(); i++)
a[i] = sub(a[i], b[i]);
return a;
}
Poly mul(const Poly &a, const Poly &b) {
int len = a.size() + b.size() + 1;
len = 1 << (int) ceil(log2(len));
static Poly prea, preb;
prea = a;
preb = b;
prea.resize(len);
preb.resize(len);
transform(&prea[0], len, 1);
transform(&preb[0], len, 1);
for (int i = 0; i < len; i++)
prea[i] = mul(prea[i], preb[i]);
transform(&prea[0], len, 0);
clean(prea);
return prea;
}
Poly inv(Poly a, int n) {
if (n == 1) return Poly(1, fast_pow(a[0], Mod - 2));
int len = 1 << ((int) ceil(log2(n)) + 1);
Poly x = inv(a, (n + 1) >> 1), y;
x.resize(len);
y.resize(len);
for (int i = 0; i < n; i++)
y[i] = a[i];
transform(&x[0], len, 1);
transform(&y[0], len, 1);
for (int i = 0; i < len; i++)
x[i] = mul(x[i], sub(2, mul(x[i], y[i])));
transform(&x[0], len, 0);
x.resize(n);
return x;
}
Poly inv(Poly a) {
return inv(a, a.size());
}
Poly deri(Poly a) {
int n = a.size();
for (int i = 1; i < n; i++)
a[i - 1] = mul(a[i], i);
a.resize(n - 1);
return a;
}
Poly inte(Poly a) {
int n = a.size();
a.resize(n + 1);
for (int i = n; i >= 1; i--)
a[i] = mul(a[i - 1], fast_pow(i, Mod - 2));
a[0] = 0;
return a;
}
Poly ln(Poly a) {
int len = a.size();
a = inte(mul(deri(a), inv(a)));
a.resize(len);
return a;
}
Poly exp(Poly a, int n) {
if (n == 1) return Poly(1, 1);
Poly x = exp(a, (n + 1) >> 1), y;
x.resize(n);
y = ln(x);
for (int i = 0; i < n; i++)
y[i] = sub(a[i], y[i]);
y[0]++;
x = mul(x, y);
x.resize(n);
return x;
}
Poly exp(Poly a) {
return exp(a, a.size());
}
int n, m, cnt[N], invf[N];
int main() {
init();
n = read(), m = read();
for (int i = 1; i <= n; i++)
cnt[read()]++;
Poly a(m + 1);
for (int i = 1; i <= m; i++) invf[i] = fast_pow(i, Mod - 2);
for (int i = 1; i <= m; i++) if (cnt[i]) {
for (int j = i; j <= m; j += i) {
a[j] = add(a[j], mul(invf[j / i], cnt[i]));
}
}
clean(a);
a = exp(a);
a.resize(m + 1);
for (int i = 1; i <= m; i++)
printf("%d\n", a[i]);
return 0;
}
LuoguP4389 付公主的背包【生成函数+多项式exp】的更多相关文章
- 洛谷P4389 付公主的背包--生成函数+多项式
题目链接戳这里 题目描述 有\(n\)件不同的商品,每件物品都有无限个,输出总体积为\([1,m]\)的方案数 思路 直接跑背包有\(30\) 考虑把每个物品的生成函数设出来,对于一件体积为\(v\) ...
- luoguP4389 付公主的背包 多项式exp
%%%dkw 话说这是个论文题来着... 考虑生成函数\(OGF\) 对于价值为\(v\)的物品,由于有\(10^5\)的件数,可以看做无限个 那么,其生成函数为\(x^0 + x^{v} + x^{ ...
- [题解] LuoguP4389 付公主的背包
这个题太神辣- 暴力背包就能获得\(30\)分的好成绩...... \(60\)分不知道咋搞..... 所以直接看\(100\)分吧\(QwQ\) 用一点生成函数的套路,对于一个体积为\(v\)的物品 ...
- 洛谷P4389 付公主的背包 [生成函数,NTT]
传送门 同样是回过头来发现不会做了,要加深一下记忆. 思路 只要听说过生成函数的人相信第一眼都可以想到生成函数. 所以我们要求 \[ ans=\prod \sum_n x^{nV}=\prod \fr ...
- luoguP4389 付公主的背包
luogu 显然这是个背包题 显然物品的数量是不用管的 所以考虑大小为\(v\)的物品可以装的体积用生成函数表示一下 \[ f(x)=\sum_{i=0}^{+\infty}x^{vi}=\frac{ ...
- 洛谷 P4389 付公主的背包 解题报告
P4389 付公主的背包 题目背景 付公主有一个可爱的背包qwq 题目描述 这个背包最多可以装\(10^5\)大小的东西 付公主有\(n\)种商品,她要准备出摊了 每种商品体积为\(V_i\),都有\ ...
- Luogu4389 付公主的背包(生成函数+多项式exp)
显然构造出生成函数,对体积v的物品,生成函数为1+xv+x2v+……=1/(1-xv).将所有生成函数乘起来得到的多项式即为答案,设为F(x),即F(x)=1/∏(1-xvi).但这个多项式的项数是Σ ...
- LOJ6077「2017 山东一轮集训 Day7」逆序对 (生成函数+多项式exp?朴素DP!)
题面 给定 n , k n,k n,k ,求长度为 n n n 逆序对个数为 k k k 的排列个数,对 1 e 9 + 7 \rm1e9+7 1e9+7 取模. 1 ≤ n , k ≤ 100 ...
- 【Luogu4389】付公主的背包
题目 传送门 解法 答案显然是\(n\)个形如\(\sum_{i \geq 1} x^{vi}\)的多项式的卷积 然而直接NTT的时间复杂度是\(O(nm\log n)\) 我们可以把每个多项式求\( ...
随机推荐
- spark必知必会的基本概念
首先我们从宏观的视角来窥视下大数据技术框架: 图1 大数据技术框架 从图1可以看出,数据源-数据收集-数据存储-资源管理,这是我们进行数据分析和处理的基本;图中的计算框架包括批处理.交互式分析和流处理 ...
- 创意时钟 人形时钟 可惜不是 https
; (function () { $('#header').css({ 'position':'relative' }).prepend('<div id="clockWrap&quo ...
- telnet 命令使用方法详解,telnet命令怎么用?
什么是Telnet? 对于Telnet的认识,不同的人持有不同的观点,可以把Telnet当成一种通信协议,但是对于入侵者而言,Telnet只是一种远程登录的工具.一旦入侵者与远程主机建立了Telnet ...
- SpringBoot 中常用注解@Controller/@RestController/@RequestMapping介绍
原文 SpringBoot 中常用注解 @Controller/@RestController/@RequestMapping介绍 @Controller 处理http请求 @Controller / ...
- CentOS配置iptables规则并使其永久生效
1. 目的 最近为了使用nginx,配置远程连接的使用需要使用iptable是设置允许外部访问80端口,但是设置完成后重启总是失效.因此百度了一下如何设置永久生效,并记录. 2. 设置 2.1 添加 ...
- hdoj2476 String painter
题意:有一刷子,能将区间内涂成同一字母.给出src,dst串,问最少涂几次? 用dp[i][j]表示区间[i,j]内最少涂的次数.len=1,2时很明显.len=3时,dp[i][j]要么就在dp[i ...
- laravel时间判断
$now = Carbon::now(); if ($now >= '2019-01-02') { }
- thinkphp得到客户端的ip
/** * 获取客户端IP地址 * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字 * @return mixed */function get_cli ...
- HDU-3790 最短路径问题(双重权值)
Problem Description 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的. Inp ...
- python 爬取京东手机图
初学urllib,高手勿喷... import re import urllib.request #函数:每一页抓取的30张图片 def craw(url,page): imagelist = []# ...