题目链接:洛谷

题目大意:现在有$n$个物品,每种物品体积为$v_i$,对任意$s\in [1,m]$,求背包恰好装$s$体积的方案数(完全背包问题)。

数据范围:$n,m\leq 10^5$


这道题,看到数据范围就知道是生成函数。
$$Ans=\prod_{i=1}^n\frac{1}{1-x^{v_i}}$$

但是这个式子直接乘会tle,我们考虑进行优化。

看见这个连乘的式子,应该是要上$\ln$.

$$Ans=\exp(\sum_{i=1}^n\ln(\frac{1}{1-x^{v_i}}))$$

接下来的问题就是如何快速计算$\ln(\frac{1}{1-x^{v_i}})$。

$$\ln(f(x))=\int f'f^{-1}dx$$

所以
$$\ln(\frac{1}{1-x^v})=\int\sum_{i=1}^{+\infty}vix^{vi-1}*(1-x^v)dx$$
$$=\int(\sum_{i=1}^{+\infty}vix^{vi-1}-\sum_{i=2}^{+\infty}v(i-1)x^{vi-1})dx$$
$$=\int(\sum_{i=1}^{+\infty}vx^{vi-1})dx$$
$$=\sum_{i=1}^{+\infty}\frac{1}{i}x^{vi}$$

然后就可以直接代公式了。

 #include<cstdio>
#include<algorithm>
#define Rint register int
using namespace std;
typedef long long LL;
const int N = , P = , G = , Gi = ;
int n, m, cnt[N], A[N];
inline int kasumi(int a, int b){
int res = ;
while(b){
if(b & ) res = (LL) res * a % P;
a = (LL) a * a % P;
b >>= ;
}
return res;
}
int R[N];
inline void NTT(int *A, int limit, int type){
for(Rint i = ;i < limit;i ++)
if(i < R[i]) swap(A[i], A[R[i]]);
for(Rint mid = ;mid < limit;mid <<= ){
int Wn = kasumi(type == ? G : Gi, (P - ) / (mid << ));
for(Rint j = ;j < limit;j += mid << ){
int w = ;
for(Rint k = ;k < mid;k ++, w = (LL) w * Wn % P){
int x = A[j + k], y = (LL) w * A[j + k + mid] % P;
A[j + k] = (x + y) % P;
A[j + k + mid] = (x - y + P) % P;
}
}
}
if(type == -){
int inv = kasumi(limit, P - );
for(Rint i = ;i < limit;i ++)
A[i] = (LL) A[i] * inv % P;
}
}
int ans[N];
inline void poly_inv(int *A, int deg){
static int tmp[N];
if(deg == ){
ans[] = kasumi(A[], P - );
return;
}
poly_inv(A, (deg + ) >> );
int limit = , L = -;
while(limit <= (deg << )){limit <<= ; L ++;}
for(Rint i = ;i < limit;i ++)
R[i] = (R[i >> ] >> ) | ((i & ) << L);
for(Rint i = ;i < deg;i ++) tmp[i] = A[i];
for(Rint i = deg;i < limit;i ++) tmp[i] = ;
NTT(tmp, limit, ); NTT(ans, limit, );
for(Rint i = ;i < limit;i ++)
ans[i] = ( - (LL) tmp[i] * ans[i] % P + P) % P * ans[i] % P;
NTT(ans, limit, -);
for(Rint i = deg;i < limit;i ++) ans[i] = ;
}
int Ln[N];
inline void get_Ln(int *A, int deg){
static int tmp[N];
poly_inv(A, deg);
for(Rint i = ;i < deg;i ++)
tmp[i - ] = (LL) i * A[i] % P;
tmp[deg - ] = ;
int limit = , L = -;
while(limit <= (deg << )){limit <<= ; L ++;}
for(Rint i = ;i < limit;i ++)
R[i] = (R[i >> ] >> ) | ((i & ) << L);
NTT(ans, limit, ); NTT(tmp, limit, );
for(Rint i = ;i < limit;i ++) Ln[i] = (LL) ans[i] * tmp[i] % P;
NTT(Ln, limit, -);
for(Rint i = deg + ;i < limit;i ++) Ln[i] = ;
for(Rint i = deg;i;i --) Ln[i] = (LL) Ln[i - ] * kasumi(i, P - ) % P;
for(Rint i = ;i < limit;i ++) tmp[i] = ans[i] = ;
Ln[] = ;
}
int Exp[N];
inline void get_Exp(int *A, int deg){
if(deg == ){
Exp[] = ;
return;
}
get_Exp(A, (deg + ) >> );
get_Ln(Exp, deg);
for(Rint i = ;i < deg;i ++) Ln[i] = (A[i] + (i == ) - Ln[i] + P) % P;
int limit = , L = -;
while(limit <= (deg << )){limit <<= ; L ++;}
for(Rint i = ;i < limit;i ++)
R[i] = (R[i >> ] >> ) | ((i & ) << L);
NTT(Exp, limit, ); NTT(Ln, limit, );
for(Rint i = ;i < limit;i ++) Exp[i] = (LL) Exp[i] * Ln[i] % P;
NTT(Exp, limit, -);
for(Rint i = deg;i < limit;i ++) Exp[i] = ;
for(Rint i = ;i < limit;i ++) Ln[i] = ans[i] = ;
}
int main(){
scanf("%d%d", &n, &m);
for(Rint i = ;i <= n;i ++){
int x;
scanf("%d", &x);
++ cnt[x];
}
for(Rint i = ;i <= m;i ++){
if(!cnt[i]) continue;
for(Rint j = i;j <= m;j += i)
A[j] = (A[j] + (LL) cnt[i] * kasumi(j / i, P - ) % P) % P;
}
get_Exp(A, m + );
for(Rint i = ;i <= m;i ++)
printf("%d\n", Exp[i]);
}

luogu4389

luogu4389 付公主的背包的更多相关文章

  1. [luogu4389]付公主的背包(多项式exp)

    完全背包方案计数问题的FFT优化.首先写成生成函数的形式:对重量为V的背包,它的生成函数为$\sum\limits_{i=0}^{+\infty}x^{Vi}=\frac{1}{1-x^{V}}$于是 ...

  2. Luogu4389 付公主的背包(生成函数+多项式exp)

    显然构造出生成函数,对体积v的物品,生成函数为1+xv+x2v+……=1/(1-xv).将所有生成函数乘起来得到的多项式即为答案,设为F(x),即F(x)=1/∏(1-xvi).但这个多项式的项数是Σ ...

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

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

  4. LuoguP4389 付公主的背包【生成函数+多项式exp】

    题目背景 付公主有一个可爱的背包qwq 题目描述 这个背包最多可以装10^5105大小的东西 付公主有n种商品,她要准备出摊了 每种商品体积为Vi,都有10^5105件 给定m,对于s\in [1,m ...

  5. 【Luogu4389】付公主的背包

    题目 传送门 解法 答案显然是\(n\)个形如\(\sum_{i \geq 1} x^{vi}\)的多项式的卷积 然而直接NTT的时间复杂度是\(O(nm\log n)\) 我们可以把每个多项式求\( ...

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

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

  7. luogu P4389 付公主的背包

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

  8. P3489 付公主的背包

    题意:n<=1e5,m<=1e5,跑n个物品1到m容量的完全背包. 考虑暴力的做法就是把一些1/(1+x^a)的多项式乘起来即可. 考虑优化,取一下ln,转化为加法,然后exp回去就好了.

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

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

随机推荐

  1. MinGW 使用 mintty 终端替代默认终端以解决界面上复制与粘贴的问题

    使用了一段时间的 cygwin,挺开心的,又尝试了下同类工具 Msys + MinGW,安装好之后发现它居然使用默认的 cmd 作为终端,界面输出内容的复制与粘贴极其不便,我记得 Cygwin 使用的 ...

  2. Java如何从服务器获取文件大小?

    在Java编程中,如何从服务器获取文件大小? 以下示例演示如何从服务器获取文件大小. package com.yiibai; import java.net.URL; import java.net. ...

  3. Android实现电话录音功能

    需求分析 电话录音是在通话的时候进行录音,所以需要使用一个服务来完成功能. 需要监听电话的状态,分为三种状态:  空闲状态 TelephonyManager.CALL_STATE_IDLE 响铃状态 ...

  4. QT动态库和静态库使用

    软件版本:QT5.12.0 + Qt Creator4.8.0 动态链接 动态链接库又叫"共享库",即sharedLib. Qt Creator中新建项目,选择"Libr ...

  5. [DLX精确覆盖] hdu 1603 A Puzzling Problem

    题意: 给你n块碎片,这些碎片不能旋转.翻折. 问你能不能用当中的某些块拼出4*4的正方形. 思路: 精确覆盖裸题了 建图就是看看每一个碎片在4*4中能放哪些位置,这个就作为行. 列就是4*4=16个 ...

  6. [1]朝花夕拾-JAVA类的执行顺序

    最近在温习java的基础,刷题刷到java的执行顺序,很汗颜,答案回答错了! 题目类似如下: package com.phpdragon.study.base; public class ExecOr ...

  7. java.util.Stack(栈)的简单使用

    import java.util.Stack; import org.junit.Before; import org.junit.Test; /** * Stack(栈)继承了Vector类,底层实 ...

  8. mui---父页面跳子页面刷新子页面

    最近在做项目,遇到一个问题,从父页面跳转到子页面,不会刷新子页面的问题. 解决方法:可以在跳转的时候,使用openWindow来进行跳转,接下来配置跳转打开页面的参数: 具体如下: mui.openW ...

  9. 为什么HTML使用<!DOCTYPE HTML>

    不管是刚接触前端,还是你已经“精通”web前端开发的内容,你应该知道在你写html的时候需要定义文档类型:你知道如果没有它,浏览器在渲染页面的时候会使用怪异模式:你知道各个浏览器在怪异模式下对各个元素 ...

  10. 自主移动机器人同时定位与地图创建(SLAM)方法概述

    1.引言: 机器人的研究越来越多的得到关注和投入,随着计算机技术和人工智能的发展,智能自主移动机器人成为机器人领域的一个重要研究方向和研究热点.移动机器人的定位和地图创建是自主移动机器人领域的热点研究 ...