题目链接:洛谷

题目大意:现在有$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. hdoj:2024

    #include <iostream> #include <string> #include <vector> using namespace std; int m ...

  2. (转载)Redis5.0重量级特性Stream尝鲜

    转 导读:Redis5.0最新重点推出了Stream的支持,给众多架构师在消息队列方面带来了新的选择,特别是Redis粉丝们绝对是一个福音.那么Redis的Stream有哪些特别的功能?跟kafka有 ...

  3. 深度解析Java 8:JDK1.8 AbstractQueuedSynchronizer的实现分析

    深度解析Java 8:JDK1.8 AbstractQueuedSynchronizer的实现分析(上) 深度解析Java 8:AbstractQueuedSynchronizer的实现分析(下) A ...

  4. Python内置类型——set

    Python中,内置类型set和frozenset用来表示集合,我们首先查看这两个类型支持的特殊对象,从而可以理解他们的特性. >>> dir(set) ['__and__', '_ ...

  5. jq ajax post body raw传json

    $.ajax( { url: '', 'data': JSON.stringify({ }), 'type': 'POST', 'processData': false, 'contentType': ...

  6. windows python3.7安装numpy问题的解决方法

    我的是win7的系统,去python官网下载python3.7安装 CMD  #打开命令窗口 pip install numpy #在cmd中输入 提示 需要c++14.0, 解决办法: 1, 进入h ...

  7. 问题:UltraISO:这个软件有问题,它制作的iso文件会造成无法正确识别。用PowerISO吧

    最近研究硬盘安装 centos7.6 (rhel 7.6)的 硬盘安装,因为原版dvd超过4G了,所以通过删除java-open-jdk的方式减少dvd光盘的大小. 但是前期用UltraISO制作的i ...

  8. Gradle 设置全局代理

    #systemProp.socks.proxyHost=127.0.0.1 #systemProp.socks.proxyPort=7077 #systemProp.https.proxyHost=1 ...

  9. OpenGL——圆公式相关变化的绘制

    #include<iostream> #include <math.h> //旧版本 固定管线 #include<Windows.h> #include <G ...

  10. 【2017.12.12】deepin安装U盘制作,支持 BIOS+UEFI,deepin_Recovery+Win PE

    U盘要求为 FAT32,MBR分区表 如果需要放 4GB 大文件,可以分两个分区,第一分区FAT32格式,放启动相关文件,第二个分区用 NTFS 格式,放其它资料. 最新 Win10 支持显示 U盘 ...