正题

题目链接:https://www.luogu.com.cn/problem/P4389


题目大意

nnn种物品,第iii种大小为viv_ivi​,数量无限。对于每个s∈[1,m]s\in[1,m]s∈[1,m]求刚好填满sss容量的方案数。

1≤n,m≤1051\leq n,m\leq 10^51≤n,m≤105


解题思路

统计和为一定值的方案数,好像可以生成函数做?

每种物品大小vvv有一个生成函数
F(x)=∑i≥0xi×v=11−xvF(x)=\sum_{i\geq 0}x^{i\times v}=\frac{1}{1-x^v}F(x)=i≥0∑​xi×v=1−xv1​
然后所有生成函数乘起来就好了,但这样是O(n2log⁡n)O(n^2\log n)O(n2logn)的比暴力还慢…

乘起来比较慢,如果lnlnln之后改成加法就好了,但是lnlnln也是O(n)O(n)O(n)的。不过我们的式子比较特殊,对于lnlnln之后求个导就会有神器的结果
ln′(1−xv)=(1−xv)′1−xv=−v×xv−11−xvln'(1-x^v)=\frac{(1-x^v)'}{1-x^v}=\frac{-v\times x^{v-1}}{1-x^v}ln′(1−xv)=1−xv(1−xv)′​=1−xv−v×xv−1​
=−v∑i≥0xv−1+v×i=-v\sum_{i\geq 0}x^{v-1+v\times i}=−vi≥0∑​xv−1+v×i
然后在积分回去就是
−∑i≥0xv+v×ii=−∑i≥1xv×ii-\sum_{i\geq 0}\frac{x^{v+v\times i}}{i}=-\sum_{i\geq 1}\frac{x^{v\times i}}{i}−i≥0∑​ixv+v×i​=−i≥1∑​ixv×i​
然后记录每个大小的物品出现了多少次,之后O(mlog⁡m)O(m\log m)O(mlogm)加系数,然后再exp+exp+exp+求逆回去就好了。

时间复杂度O(n+mlog⁡m)O(n+m\log m)O(n+mlogm)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=4e5+10,P=998244353;
ll n,c,l,r[N],f[N],v[N],inv[N];
ll t1[N],t2[N],t3[N],t4[N],t5[N],t6[N];
ll power(ll x,ll b){ll ans=1;while(b){if(b&1)ans=ans*x%P;x=x*x%P;b>>=1;}return ans;
}
void Glen(ll m){n=1;while(n<=m)n<<=1;for(ll i=0;i<n;i++)r[i]=(r[i>>1]>>1)|((i&1)?(n>>1):0);return;
}
void NTT(ll *f,ll op){for(ll i=0;i<n;i++)if(i<r[i])swap(f[i],f[r[i]]);for(ll p=2;p<=n;p<<=1){ll len=p>>1,tmp=power(3,(P-1)/p);if(op==-1)tmp=power(tmp,P-2);for(ll k=0;k<n;k+=p){ll buf=1;for(ll i=k;i<k+len;i++){ll tt=f[i+len]*buf%P;f[i+len]=(f[i]-tt+P)%P;f[i]=(f[i]+tt)%P;buf=buf*tmp%P;}}}if(op==-1){ll inv=power(n,P-2);for(ll i=0;i<n;i++)f[i]=f[i]*inv%P;}return;
}
void GetInv(ll *f,ll *g,ll m){if(m==1){g[0]=power(f[0],P-2);return;}GetInv(f,g,m>>1);Glen(m);for(ll i=0;i<m;i++)t1[i]=f[i],t2[i]=g[i];NTT(t1,1);NTT(t2,1);for(ll i=0;i<n;i++)t1[i]=t1[i]*t2[i]%P*t2[i]%P;NTT(t1,-1);for(ll i=0;i<m;i++)g[i]=(g[i]*2-t1[i]+P)%P;for(ll i=0;i<n;i++)t1[i]=t2[i]=0;return;
}
void GetD(ll *f,ll *g,ll n){for(ll i=0;i<n-1;i++)g[i]=f[i+1]*(i+1)%P;g[n-1]=0;return;
}
void GetJ(ll *f,ll *g,ll n){for(ll i=n-1;i>0;i--)g[i]=f[i-1]*power(i,P-2)%P;g[0]=0;return;
}
void GetLn(ll *f,ll *g,ll m){Glen(m);GetD(f,t3,n);GetInv(f,t4,n);Glen(m);Glen(n);NTT(t3,1);NTT(t4,1);for(ll i=0;i<n;i++)t3[i]=t3[i]*t4[i];NTT(t3,-1);GetJ(t3,g,n);for(ll i=0;i<n;i++)t3[i]=t4[i]=0;return;
}
void GetExp(ll *f,ll *g,ll m){if(m==1){g[0]=1;return;}GetExp(f,g,m>>1);GetLn(g,t5,m);Glen(m);for(ll i=0;i<m;i++)t6[i]=f[i];for(ll i=m;i<n;i++)t5[i]=0;NTT(t5,1);NTT(t6,1);NTT(g,1);for(ll i=0;i<n;i++)g[i]=g[i]*(1-t5[i]+t6[i]+P)%P;NTT(g,-1);for(ll i=m;i<n;i++)g[i]=0;return;
}
signed main()
{scanf("%lld%lld",&c,&l);inv[1]=1;for(ll i=2;i<N;i++)inv[i]=P-(P/i)*inv[P%i]%P;for(ll i=1;i<=c;i++){ll x;scanf("%lld",&x);v[x]++;}Glen(l);for(ll i=l;i>=1;i--){ll w=v[i];v[i]=0;for(ll j=i;j<n;j+=i)(v[j]+=w*(P-inv[j/i])%P)%=P;}ll p=n;GetExp(v,f,n);for(ll i=0;i<n;i++)v[i]=0;GetInv(f,v,n);for(ll i=1;i<=l;i++)printf("%lld\n",v[i]);return 0;
}

P4389-付公主的背包【生成函数,多项式exp】相关推荐

  1. P4389 付公主的背包(生成函数,多项式exp)

    P4389 付公主的背包 考虑生成函数有: ∏i=1n11−xvi对其取对数得,∑i=1nln⁡11−xviF(x)=11−xv,G(x)=ln⁡F(x)G(x)=∫F′(x)F(x)dxG(x)=∫ ...

  2. P4389 付公主的背包(生成函数/多项式)

    P4389 付公主的背包 https://www.luogu.com.cn/problem/solution/P4389 经典生成函数问题 求解无限背包问题,我们可以将每个物品看作一个多项式,那么最后 ...

  3. 洛谷 P4389 付公主的背包 多项式exp

    题目描述 这个背包最多可以装10510^5105大小的东西 付公主有nnn种商品,她要准备出摊了 每种商品体积为ViV_iVi​,都有10510^5105件 给定mmm,对于s∈[1,m]s\in [ ...

  4. 洛谷P4389:付公主的背包(多项式、生成函数)

    对于一些生成函数累乘的题目,也许可以通过求 ln⁡\lnln 转化为累加问题从而完成简化. 解析 不难写出对于单个物品 kkk 的生成函数: ∑i=1xVi=11−xVK\sum_{i=1}x^{Vi ...

  5. 【洛谷4389】付公主的背包(生成函数,多项式运算)

    [洛谷4389]付公主的背包(生成函数,多项式运算) 题面 有一个容量最多为\(10^5\)的背包 有\(n\)种物品,数量无限,题解是\(v_i\) 给定一个\(m\),求所有\(s\in[1,m] ...

  6. [luogu4389]付公主的背包

    前言 一道巧妙的推式子题 题目相关 链接 题目大意 给出nnn个商品,第iii个商品的体积为viv_ivi​,并且有无限个 现在给出一个mmm,对背包大小s∈[1,m]s\in[1,m]s∈[1,m] ...

  7. luogu4389 付公主的背包

    题目链接:洛谷 题目大意:现在有$n$个物品,每种物品体积为$v_i$,对任意$s\in [1,m]$,求背包恰好装$s$体积的方案数(完全背包问题). 数据范围:$n,m\leq 10^5$ 这道题 ...

  8. P5748-集合划分计数【EGF,多项式exp】

    正题 题目链接:https://www.luogu.com.cn/problem/P5748 题目大意 求将nnn的排列分成若干个无序非空集合的方案. 输出答案对9982443539982443539 ...

  9. 生成函数多项式操作合集

    一.生成函数与多项式乘法. 众所周知,生成函数是OI中的计数利器,而很多生成函数的题目需要快速计算式子中的多项式运算,所以本篇主要是介绍多项式运算的. 值得注意的是,这里很多奇怪的多项式运算本来是不存 ...

最新文章

  1. 038_Unicode对照表四
  2. linux shell脚本:通过API实现git仓库从gitee向gitlab的批量迁移(gitlab api)
  3. 雷达波形样式_案例分析 | 基于XSIM的雷达电子对抗仿真
  4. LeetCode 695 Max Area of Island
  5. 静默安装oracle后,启动oem报错,解决方法!
  6. SharePoint 站点出现Http 503 错误
  7. Oracle DBA课程系列笔记(4)
  8. 【Python笔记】使用 re 模块实现正则表达式操作
  9. 常见算法之12---求a^n%p
  10. 计算机Java毕设项目-PPT答辩篇
  11. java 长方形正方形_JAVA将长方形图片剪裁成正方形。
  12. 转载-卷影复制服务(VSS)详细介绍
  13. VS LNK2001--链接器工具错误
  14. 转:明茨伯格:组织不需要英雄,只需要有雅量的领导
  15. 51cto python数据分析系列课程 55g_Python 3 数据分析与挖掘系列课程完整版
  16. 【读书笔记】《JS函数式编程指南》(一)
  17. HMACSHA512
  18. 使用scrapy爬取京东产品详细信息
  19. 最新Android 9.0 Pie,你想知道的都在这了
  20. 【TJOI 2015】弦论

热门文章

  1. java环境怎样搭建_如何学习JAVA?怎么搭建JAVA环境?怎么安装JDK?
  2. python多线程 不在main_从python线程(不是main)启动pyQt线程有什么不...
  3. 升级总代分享思路_桃生企业至尊七郎瓷砖新展厅全新升级惊艳亮相
  4. python切片原理_深度解析Python切片
  5. 空值为0非空为1_万达广场4周年,1降到底!0元送万张杂技团门票、人气餐饮6.8折,这波周年庆我先锁为敬...
  6. mysql中如何计算党龄_党员的党龄如何计算?
  7. 用java求直角三角形的面积_JAVA 已知三角形的三个边判断 是否为直角三角形,如果是求面积!...
  8. 噪声与振动控制工程手册_仨亿技术丨工程机械噪声与控制分析
  9. java static new_java静态类new的对象是否能被回收?
  10. php html asp .net iis tomcat,iis+apache+tomcat 整合共享80口 支持ASP .NET JSP PHP全能WEB服务...