注意

初始化的时候要这样写

  1. for(int i=1,x;i<=n;i++){
  2. scanf("%d",&x);
  3. v[x]++;
  4. }
  5. for(int i=1;i<=m;i++){
  6. if(v[i]){
  7. for(int j=1;j<=m/i;j++)
  8. a[i*j]=(a[i*j]+1LL*v[i]*invx[j]%MOD)%MOD;
  9. }
  10. }

这样写的复杂度是调和级数(\(O(n\log n)\))

不能这样写

  1. for(int i=1;i<=n;i++){
  2. scanf("%d",&v[i]);
  3. for(int j=0;v[i]*j-1<=m;j++)
  4. if(v[i]*j-1>=0)
  5. a[v[i]*j-1]+=v[i];
  6. }

因为权值可能重复,这样的话复杂度就不对了

思路

题目要求的答案是

\[\prod_{k=1}^n \sum_{i=1}^\infty x^{iV_k}
\]

直接卷积的复杂度是\(O(nm\log m)\),考虑一个化乘法为加法的思路:把所有多项式取\(\ln\)之后加起来求\(\exp\)

\[A_k(x)=\sum_{i=1}^\infty x^{iV_k}=\frac{1}{1-x^{V_k}}
\]

\[\prod_{k=1}^n e^{\ln(A(x))}= e^{\sum_{k=1}^n \ln(A(x))}
\]

所以问题转化成了如何快速求\(\sum_{k=1}^n \ln(A(x))​\)

\[\begin{align} &\sum_{k=1}^n \ln(A(x))\\=& \sum_{k=1}^n \int \frac{A'(x)}{A(x)}\\=&\int \sum_{k=1}^n \frac{(\sum_{i=1}^\infty x^{iV_k})'}{\frac{1}{1-x^{V_k}}}\\=&\int \sum_{k=1}^n (1-x^{V_k})\sum_{i=1}^\infty iV_kx^{iV_k-1}\\=&\int \sum_{k=1}^n V_k\sum_{i=1}^{\infty} x^{iV_k-1}\\=&\sum_{k=1}^n\sum_{i=1}^{\infty}\frac{V_{k}}{iV_k}x^{iV_k}\\=&\sum_{k=1}^n\sum_{i=1}^{\infty}\frac{1}{i}x^{iV_k}\end{align}
\]

代码

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. const int MAXN = 300000;
  6. const int G = 3;
  7. const int invG = 332748118;
  8. const int MOD = 998244353;
  9. int rev[MAXN],invx[MAXN];
  10. int pow(int a,int b){
  11. int ans=1;
  12. while(b){
  13. if(b&1)
  14. ans=(1LL*ans*a)%MOD;
  15. a=(1LL*a*a)%MOD;
  16. b>>=1;
  17. }
  18. return ans;
  19. }
  20. void cal_rev(int *rev,int n,int lim){
  21. for(int i=0;i<n;++i)
  22. rev[i]=(rev[i>>1]>>1)|((i&1)<<(lim-1));
  23. }
  24. void NTT(int *a,int opt,int n,int lim){
  25. for(int i=0;i<n;++i)
  26. if(i<rev[i])
  27. swap(a[i],a[rev[i]]);
  28. for(int i=2;i<=n;i<<=1){
  29. int len=i/2;
  30. int tmp=pow((opt)?G:invG,(MOD-1)/i);
  31. for(int j=0;j<n;j+=i){
  32. int arr=1;
  33. for(int k=j;k<j+len;k++){
  34. int t=(1LL*a[k+len]*arr)%MOD;
  35. a[k+len]=(a[k]-t+MOD)%MOD;
  36. a[k]=(a[k]+t)%MOD;
  37. arr=(1LL*arr*tmp)%MOD;
  38. }
  39. }
  40. }
  41. if(!opt){
  42. int invN=pow(n,MOD-2);
  43. for(int i=0;i<n;++i)
  44. a[i]=(1LL*a[i]*invN)%MOD;
  45. }
  46. }
  47. void mul(int *a,int *b,int &at,int bt){
  48. static int tmp1[MAXN];
  49. int num=(at+bt),n=1,lim=0;
  50. while(n<=(num+2))
  51. n<<=1,lim++;
  52. for(int i=0;i<n;++i)
  53. tmp1[i]=b[i];
  54. cal_rev(rev,n,lim);
  55. NTT(a,1,n,lim);
  56. NTT(tmp1,1,n,lim);
  57. for(int i=0;i<n;++i)
  58. a[i]=(1LL*a[i]*tmp1[i])%MOD;
  59. NTT(a,0,n,lim);
  60. at=num;
  61. }
  62. void inv(int *a,int *b,int dep,int &midlen,int &midlim){
  63. if(dep==1){
  64. b[0]=pow(a[0],MOD-2);
  65. return;
  66. }
  67. inv(a,b,(dep+1)>>1,midlen,midlim);
  68. static int tmp[MAXN];
  69. while((dep<<1)>midlen)
  70. midlen<<=1,midlim++;
  71. for(int i=0;i<dep;++i)
  72. tmp[i]=a[i];
  73. for(int i=dep;i<midlen;++i)
  74. tmp[i]=0;
  75. cal_rev(rev,midlen,midlim);
  76. NTT(tmp,1,midlen,midlim);
  77. NTT(b,1,midlen,midlim);
  78. for(int i=0;i<midlen;++i)
  79. b[i]=1LL*b[i]*(2-1LL*tmp[i]*b[i]%MOD+MOD)%MOD;
  80. NTT(b,0,midlen,midlim);
  81. for(int i=dep;i<midlen;++i)
  82. b[i]=0;
  83. }
  84. void qd(int *a,int &at){
  85. for(int i=0;i<at;++i)
  86. a[i]=(1LL*a[i+1]*(i+1))%MOD;
  87. a[at]=0;
  88. at--;
  89. }
  90. void jf(int *a,int &at){
  91. at++;
  92. for(int i=at;i>=1;i--)
  93. a[i]=(1LL*a[i-1]*invx[i])%MOD;
  94. a[0]=0;
  95. }
  96. void ln(int *a,int *b,int &at){
  97. static int tmp[MAXN];
  98. int midlen=1,midlim=0,tmpt=at,bt=at;
  99. for(int i=0;i<=at;++i)
  100. tmp[i]=a[i];
  101. inv(a,b,at+1,midlen,midlim);
  102. qd(tmp,tmpt);
  103. mul(b,tmp,at,tmpt);
  104. jf(b,tmpt);
  105. for(int i=bt+1;i<=at;++i)
  106. b[i]=0;
  107. at=bt;
  108. }
  109. void exp(int *a,int *b,int dep){
  110. if(dep==1){
  111. b[0]=1;
  112. return;
  113. }
  114. exp(a,b,(dep+1)>>1);
  115. static int tmp1[MAXN];
  116. for(int i=0;i<dep;++i)
  117. tmp1[i]=0;
  118. ln(b,tmp1,dep);
  119. for(int i=0;i<dep;++i)
  120. tmp1[i]=(a[i]-tmp1[i]+MOD)%MOD;
  121. tmp1[0]+=1;
  122. int midlen=dep-1;
  123. mul(b,tmp1,midlen,dep-1);
  124. for(int i=dep;i<midlen;++i)
  125. b[i]=0;
  126. }
  127. void inv_init(int n){
  128. invx[0]=0;
  129. invx[1]=1;
  130. for(int i=2;i<=n;i++)
  131. invx[i]=1LL*(MOD-MOD/i)*invx[MOD%i]%MOD;
  132. }
  133. int a[MAXN],b[MAXN],n,m,v[MAXN];
  134. int main(){
  135. scanf("%d %d",&n,&m);
  136. inv_init(m+1);
  137. // for(int i=1;i<=n;i++){
  138. // scanf("%d",&v[i]);
  139. // for(int j=0;v[i]*j-1<=m;j++)
  140. // if(v[i]*j-1>=0)
  141. // a[v[i]*j-1]+=v[i];
  142. // }
  143. for(int i=1,x;i<=n;i++){
  144. scanf("%d",&x);
  145. v[x]++;
  146. }
  147. for(int i=1;i<=m;i++){
  148. if(v[i]){
  149. for(int j=1;j<=m/i;j++)
  150. a[i*j]=(a[i*j]+1LL*v[i]*invx[j]%MOD)%MOD;
  151. }
  152. }
  153. // jf(a,m);
  154. exp(a,b,m+1);
  155. for(int i=1;i<=m;i++)
  156. printf("%d\n",b[i]);
  157. return 0;
  158. }

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

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

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

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

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

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

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

  4. luogu P4389 付公主的背包

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

  5. 洛谷P4389 付公主的背包 [生成函数,NTT]

    传送门 同样是回过头来发现不会做了,要加深一下记忆. 思路 只要听说过生成函数的人相信第一眼都可以想到生成函数. 所以我们要求 \[ ans=\prod \sum_n x^{nV}=\prod \fr ...

  6. [洛谷P4389]付公主的背包

    题目大意:有$n(n\leqslant10^5)$种物品,第$i$个物品体积为$v_i$,都有$10^5$件.给定$m(m\leqslant10^5)$,对于$s\in [1,m]$,请你回答用这些商 ...

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

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

  8. Solution -「洛谷 P4389」付公主的背包

    \(\mathcal{Description}\)   Link.   容量为 \(n\),\(m\) 种物品的无限背包,求凑出每种容量的方案数,对 \(998244353\) 取模.   \(n,m ...

  9. luogu4389 付公主的背包

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

随机推荐

  1. ASM: Active Shape Models--Their Training and Application

    这篇论文的前半部分基本就是论文<Training Models of Shape from Sets of Examples>的全部内容,只不过多两个应用示例,后半部分在PDM模型的基础上 ...

  2. Linux服务器在SSH客户端如何实现免密登录

    一.SSH客户端Setting 配置 key ,  创建生成公钥导出文件. 二.服务器 master 上生成密钥 通过执行命令 ssh-keygen -t rsa 来生成我们需要的密钥. ssh-ke ...

  3. VUE-006-通过路由 router.push 传递 params 参数(路由 name 识别,请求链接不显示)

    在前端页面表单列表修改时,经常需要在页面切换的时候,传递需要修改的表单内容,通常可通过路由进行表单参数的传递. 首先,配置页面跳转路由.在 router/index.js 中配置相应的页面跳转路由,如 ...

  4. socket通信的遇到的问题1

    /*使用select对fd可读写,格式*/ while(ctrl){ //// FD_ZERO(&readSocketSet); FD_SET(readSocketFd,&readSo ...

  5. linux获取网络信息函数

    获取IP地址 int sys_getIP(char *ip_addr) { ] = {"ifconfig eth0 | grep inet | cut -d: -f2 | cut -d' ' ...

  6. SpringMVC Web项目升级为Springboot项目(一)

    一.项目改为Springboot项目 1.将pom中所有spring相关依赖删除,添加spring-boot-starter及spring-boot-starter-web(项目中可能有其他sprin ...

  7. Java面试题和解答(四)

    1.JVM什么情况下会GC,GC策略有哪些 当应用程序分配新的对象,GC的代的预算大小已经达到阈值,比如GC的第0代已满:代码主动显式调用System.GC.Collect():其他特殊情况,比如,系 ...

  8. 337A

    #include <stdio.h> #include <stdlib.h> #define MAXSIZE 60 int comp_inc(const void *first ...

  9. 2019.04.26 mongaodb

    打开服务  mongod.exe --dbpath E:\Develop\mongodb_64\data\db 在安装和打开服务之前要建一个db  文件的存储位置 然后打开服务 打开服务之后  打开图 ...

  10. sed memo 2

    配置文件注释过滤 示例文件 [user_00@txyun test]$ cat sed_test # comment aaaaaaaaaaa bbbb #comment cccc dddd fffo ...