注意

初始化的时候要这样写

    for(int i=1,x;i<=n;i++){
scanf("%d",&x);
v[x]++;
}
for(int i=1;i<=m;i++){
if(v[i]){
for(int j=1;j<=m/i;j++)
a[i*j]=(a[i*j]+1LL*v[i]*invx[j]%MOD)%MOD;
}
}

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

不能这样写

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

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

思路

题目要求的答案是

\[\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}
\]

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 300000;
const int G = 3;
const int invG = 332748118;
const int MOD = 998244353;
int rev[MAXN],invx[MAXN];
int pow(int a,int b){
int ans=1;
while(b){
if(b&1)
ans=(1LL*ans*a)%MOD;
a=(1LL*a*a)%MOD;
b>>=1;
}
return ans;
}
void cal_rev(int *rev,int n,int lim){
for(int i=0;i<n;++i)
rev[i]=(rev[i>>1]>>1)|((i&1)<<(lim-1));
}
void NTT(int *a,int opt,int n,int lim){
for(int i=0;i<n;++i)
if(i<rev[i])
swap(a[i],a[rev[i]]);
for(int i=2;i<=n;i<<=1){
int len=i/2;
int tmp=pow((opt)?G:invG,(MOD-1)/i);
for(int j=0;j<n;j+=i){
int arr=1;
for(int k=j;k<j+len;k++){
int t=(1LL*a[k+len]*arr)%MOD;
a[k+len]=(a[k]-t+MOD)%MOD;
a[k]=(a[k]+t)%MOD;
arr=(1LL*arr*tmp)%MOD;
}
}
}
if(!opt){
int invN=pow(n,MOD-2);
for(int i=0;i<n;++i)
a[i]=(1LL*a[i]*invN)%MOD;
}
}
void mul(int *a,int *b,int &at,int bt){
static int tmp1[MAXN];
int num=(at+bt),n=1,lim=0;
while(n<=(num+2))
n<<=1,lim++;
for(int i=0;i<n;++i)
tmp1[i]=b[i];
cal_rev(rev,n,lim);
NTT(a,1,n,lim);
NTT(tmp1,1,n,lim);
for(int i=0;i<n;++i)
a[i]=(1LL*a[i]*tmp1[i])%MOD;
NTT(a,0,n,lim);
at=num;
}
void inv(int *a,int *b,int dep,int &midlen,int &midlim){
if(dep==1){
b[0]=pow(a[0],MOD-2);
return;
}
inv(a,b,(dep+1)>>1,midlen,midlim);
static int tmp[MAXN];
while((dep<<1)>midlen)
midlen<<=1,midlim++;
for(int i=0;i<dep;++i)
tmp[i]=a[i];
for(int i=dep;i<midlen;++i)
tmp[i]=0;
cal_rev(rev,midlen,midlim);
NTT(tmp,1,midlen,midlim);
NTT(b,1,midlen,midlim);
for(int i=0;i<midlen;++i)
b[i]=1LL*b[i]*(2-1LL*tmp[i]*b[i]%MOD+MOD)%MOD;
NTT(b,0,midlen,midlim);
for(int i=dep;i<midlen;++i)
b[i]=0;
}
void qd(int *a,int &at){
for(int i=0;i<at;++i)
a[i]=(1LL*a[i+1]*(i+1))%MOD;
a[at]=0;
at--;
}
void jf(int *a,int &at){
at++;
for(int i=at;i>=1;i--)
a[i]=(1LL*a[i-1]*invx[i])%MOD;
a[0]=0;
}
void ln(int *a,int *b,int &at){
static int tmp[MAXN];
int midlen=1,midlim=0,tmpt=at,bt=at;
for(int i=0;i<=at;++i)
tmp[i]=a[i];
inv(a,b,at+1,midlen,midlim);
qd(tmp,tmpt);
mul(b,tmp,at,tmpt);
jf(b,tmpt);
for(int i=bt+1;i<=at;++i)
b[i]=0;
at=bt;
}
void exp(int *a,int *b,int dep){
if(dep==1){
b[0]=1;
return;
}
exp(a,b,(dep+1)>>1);
static int tmp1[MAXN];
for(int i=0;i<dep;++i)
tmp1[i]=0;
ln(b,tmp1,dep);
for(int i=0;i<dep;++i)
tmp1[i]=(a[i]-tmp1[i]+MOD)%MOD;
tmp1[0]+=1;
int midlen=dep-1;
mul(b,tmp1,midlen,dep-1);
for(int i=dep;i<midlen;++i)
b[i]=0;
}
void inv_init(int n){
invx[0]=0;
invx[1]=1;
for(int i=2;i<=n;i++)
invx[i]=1LL*(MOD-MOD/i)*invx[MOD%i]%MOD;
}
int a[MAXN],b[MAXN],n,m,v[MAXN];
int main(){
scanf("%d %d",&n,&m);
inv_init(m+1);
// for(int i=1;i<=n;i++){
// scanf("%d",&v[i]);
// for(int j=0;v[i]*j-1<=m;j++)
// if(v[i]*j-1>=0)
// a[v[i]*j-1]+=v[i];
// }
for(int i=1,x;i<=n;i++){
scanf("%d",&x);
v[x]++;
}
for(int i=1;i<=m;i++){
if(v[i]){
for(int j=1;j<=m/i;j++)
a[i*j]=(a[i*j]+1LL*v[i]*invx[j]%MOD)%MOD;
}
}
// jf(a,m);
exp(a,b,m+1);
for(int i=1;i<=m;i++)
printf("%d\n",b[i]);
return 0;
}

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. Logstash - Working with plugins(使用插件)

    本章节开始介绍logstash的插件及功能,插件对于logstash来说非常重要,按类别分为:input.filter.codec.output四种类型. logstash有非常丰富的插件,通过安装目 ...

  2. 彻底清空SharePoint回收站(仅限IE)

    1.导航到回收站页面2.F12,在控制台输入javascript:emptyItems()3.回车 4.点击确定即可 注意:这种方法可能只适用于Internet Explorer

  3. openpyxl.utils.exceptions.IllegalCharacterError

    如果是手动调用 xlwt 这种第三方库除了错可能没法找错误,但是从错误中我们看到错误是由 openpyxl 抛出的,我们试着从 openpyxl 中找解决方案 出错处的代码 value = value ...

  4. Android Studio旧版(内含SDK)安装和环境变量配置 转自I-T枭

    win10下Android Studio和SDK下载.安装和环境变量配置 ------made by siwuxie095 转自I-T枭https://me.csdn.net/hahahhahahah ...

  5. 多个页面引用公共的头部 header.html 和尾部 footer.html

    方法:通过load()函数,引入公共头部和尾部文件; js代码预览: $(".headerPage").load("header.html"); $(" ...

  6. mipush ionic3 线上push

    <dict> <key>aps-environment</key> <string>production</string> </dic ...

  7. patA1059 Prime Factors

    这个问题叫做质因子分解,花了大概两个小时写对了.这道题细节挺多的,书上提到了几点,一个是n=1的话需要特判.有一个很容易错的点就是n一开始要先用一个变量保存起来,不保存的话后面有点麻烦,所以建议还是先 ...

  8. Cocos Creator 获取当前 Pageview 翻页到第几页的事件索引

    新建一个js,叫做 pageAction写一个方法 pageViewClick:function(event,coustom){ var node = event.node; this.pageInd ...

  9. 北京大学Cousera学习笔记--2-计算导论与C语言基础-第一讲.计算机的基本原理-图灵机

    有限状态读写头从一个初始状态开始,对存储器上的输入数据进行读或写操作,经过有限步操作之后停机,此时存储器上的输出数据就是计算结果 (1) 图灵机的构成: 1.一条存储带:双向无限延长:上有一个个的小方 ...

  10. spark MLlib实现的基于朴素贝叶斯(NaiveBayes)的中文文本自动分类

    1.自动文本分类是对大量的非结构化的文字信息(文本文档.网页等)按照给定的分类体系,根据文字信息内容分到指定的类别中去,是一种有指导的学习过程. 分类过程采用基于统计的方法和向量空间模型可以对常见的文 ...