luogu4389 付公主的背包
题目链接:洛谷
题目大意:现在有$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 付公主的背包的更多相关文章
- [luogu4389]付公主的背包(多项式exp)
完全背包方案计数问题的FFT优化.首先写成生成函数的形式:对重量为V的背包,它的生成函数为$\sum\limits_{i=0}^{+\infty}x^{Vi}=\frac{1}{1-x^{V}}$于是 ...
- Luogu4389 付公主的背包(生成函数+多项式exp)
显然构造出生成函数,对体积v的物品,生成函数为1+xv+x2v+……=1/(1-xv).将所有生成函数乘起来得到的多项式即为答案,设为F(x),即F(x)=1/∏(1-xvi).但这个多项式的项数是Σ ...
- 洛谷 P4389 付公主的背包 解题报告
P4389 付公主的背包 题目背景 付公主有一个可爱的背包qwq 题目描述 这个背包最多可以装\(10^5\)大小的东西 付公主有\(n\)种商品,她要准备出摊了 每种商品体积为\(V_i\),都有\ ...
- LuoguP4389 付公主的背包【生成函数+多项式exp】
题目背景 付公主有一个可爱的背包qwq 题目描述 这个背包最多可以装10^5105大小的东西 付公主有n种商品,她要准备出摊了 每种商品体积为Vi,都有10^5105件 给定m,对于s\in [1,m ...
- 【Luogu4389】付公主的背包
题目 传送门 解法 答案显然是\(n\)个形如\(\sum_{i \geq 1} x^{vi}\)的多项式的卷积 然而直接NTT的时间复杂度是\(O(nm\log n)\) 我们可以把每个多项式求\( ...
- 洛谷P4389 付公主的背包--生成函数+多项式
题目链接戳这里 题目描述 有\(n\)件不同的商品,每件物品都有无限个,输出总体积为\([1,m]\)的方案数 思路 直接跑背包有\(30\) 考虑把每个物品的生成函数设出来,对于一件体积为\(v\) ...
- luogu P4389 付公主的背包
传送门 神仙题鸭!orz dkw 暴力就是完全背包 而完全背包可以和生成函数扯上关系,记第i种物品质量为\(a_i\),那么这种物品的生成函数\(G(i)=\sum_{j=0}^{\infty}x^{ ...
- P3489 付公主的背包
题意:n<=1e5,m<=1e5,跑n个物品1到m容量的完全背包. 考虑暴力的做法就是把一些1/(1+x^a)的多项式乘起来即可. 考虑优化,取一下ln,转化为加法,然后exp回去就好了.
- 洛谷 P4389: 付公主的背包
题目传送门:洛谷 P4389. 题意简述: 有 \(n\) 个物品,每个物品都有无限多,第 \(i\) 个物品的体积为 \(v_i\)(\(v_i\le m\)). 问用这些物品恰好装满容量为 \(i ...
随机推荐
- js调用winform程序(带参数)
我们会发现,我们点击迅雷下载的时候 网页可以调用应用程序,而且连接会传入迅雷,这个是怎么做到的呢? 原理: 先注册表中添加软件的具体信息,然后通过 href 可以直接调用 1.写入注册表信息,注册, ...
- Java知多少(66)输入输出(IO)和流的概述
输入输出(I/O)是指程序与外部设备或其他计算机进行交互的操作.几乎所有的程序都具有输入与输出操作,如从键盘上读取数据,从本地或网络上的文件读取数据或写入数据等.通过输入和输出操作可以从外界接收信息, ...
- Spark学习笔记——读写HDFS
使用Spark读写HDFS中的parquet文件 文件夹中的parquet文件 build.sbt文件 name := "spark-hbase" version := " ...
- 将本地代码上传github
建立本地仓库 1.首先进入text文件夹 cd d:text 首先进入text文件夹 2.执行指令:git init 执行git init 初始化成功后你会发现项目里多了一个隐藏文件夹.git 隐藏的 ...
- Java处理Exception无法捕获的异常
场景: 使用try...catch(Exception e){}来捕获异常,执行过程中线程中断或阻塞了,但是catch块中却并没有捕获到异常信息. try{ // 此处可能是调用一个远程的接口,或是调 ...
- java导出json格式文件
生成json文件代码: import java.io.File; import java.io.FileWriter; import java.io.Writer; public class Crea ...
- /usr/bin/ld: cannot find -lncurses是咋回事?
你的系統是32位的還是64位的? 如果是32位的就用:sudo apt-get install libncurses5-dev 如果是64位的,就用:sudo apt-get install lib3 ...
- [原]Jenkins(九)---jenkins分别发布多个项目到多个远程主机
/** * lihaibo * 文章内容都是根据自己工作情况实践得出. * 版权声明:本博客欢迎转发,但请保留原作者信息! http://www.cnblogs.com/horizonli/p/533 ...
- Unity3D Shader 高斯模糊
//Shader Shader "Hidden/GaussianBlur" { Properties { _MainTex ("Texture", 2D) = ...
- day_5.19 py总结②