题目链接:洛谷

题目大意:现在有$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. No service of type Factory<LoggingManagerInternal> available in ProjectScopeService

    导入GitHub上下载的项目时报错 No service of type Factory<LoggingManagerInternal> available in ProjectScope ...

  2. 正确释放WORD对象(COM组件) COMException: 被调用的对象已与其客户端断开连接

    本来form method=post本页面 修改为其他页面 action=save.aspx后没问题 其他问题可参考以下: 引自:http://topic.csdn.net/u/20090108/17 ...

  3. localhost兼容js不能用

  4. 仿迅雷播放器教程 -- C++ windows界面库对比(11)

    从上一篇文章中可以看出,C++的界面方向还很弱,没有任何一个界面库可以一统天下,所以才造成了界面库百家争鸣的情况. 从时间上看: 1.出来最早的是QT,1991年就有了. 2.VC++ 虽然1992年 ...

  5. ios开发之--valueForKeyPath的用法

    1.获取数组中的平均值,最大值,最小值,总和,代码如下: NSArray *ary = @[@,@,@,@,@,@,@]; [self caculateArray:ary]; -(NSString * ...

  6. mtr

    一般在windows 来判断网络连通性用ping 和tracert,ping的话可以来判断丢包率,tracert可以用来跟踪路由,在Linux中有一个更好的网络连通性判断工具,它可以结合ping ns ...

  7. 配置nginx实现windows/iis应用负载均衡

    nginx是俄罗斯人开发的一款跨平台的高性能HTTP和反向代理服务器,可以利用它实现web应用服务器的负载均衡. 反向代理是指将用户请求通过代理服务器转发给后端内部网络的应用服务器,典型的应用比如配置 ...

  8. 【BZOJ2671】Calc 数学

    [BZOJ2671]Calc Description 给出N,统计满足下面条件的数对(a,b)的个数: 1.1<=a<b<=N 2.a+b整除a*b Input 一行一个数N Out ...

  9. D - Wireless Network

    来源poj2236 An earthquake takes place in Southeast Asia. The ACM (Asia Cooperated Medical team) have s ...

  10. maven assembly plugin使用

    使用场景 在使用maven来管理项目时,项目除了web项目,还有可能为控制台程序,一般用于开发一些后台服务的程序.最近在工作中也遇到了这种场景,使用quartz开发一个任务调度程序.程序中依赖很多ja ...