P4389 付公主的背包
注意
初始化的时候要这样写
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];
}
因为权值可能重复,这样的话复杂度就不对了
思路
题目要求的答案是
\]
直接卷积的复杂度是\(O(nm\log m)\),考虑一个化乘法为加法的思路:把所有多项式取\(\ln\)之后加起来求\(\exp\)
设
\]
即
\]
所以问题转化成了如何快速求\(\sum_{k=1}^n \ln(A(x))\)
\]
代码
#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 付公主的背包的更多相关文章
- 洛谷 P4389 付公主的背包 解题报告
P4389 付公主的背包 题目背景 付公主有一个可爱的背包qwq 题目描述 这个背包最多可以装\(10^5\)大小的东西 付公主有\(n\)种商品,她要准备出摊了 每种商品体积为\(V_i\),都有\ ...
- 洛谷 P4389: 付公主的背包
题目传送门:洛谷 P4389. 题意简述: 有 \(n\) 个物品,每个物品都有无限多,第 \(i\) 个物品的体积为 \(v_i\)(\(v_i\le m\)). 问用这些物品恰好装满容量为 \(i ...
- 洛谷P4389 付公主的背包--生成函数+多项式
题目链接戳这里 题目描述 有\(n\)件不同的商品,每件物品都有无限个,输出总体积为\([1,m]\)的方案数 思路 直接跑背包有\(30\) 考虑把每个物品的生成函数设出来,对于一件体积为\(v\) ...
- luogu P4389 付公主的背包
传送门 神仙题鸭!orz dkw 暴力就是完全背包 而完全背包可以和生成函数扯上关系,记第i种物品质量为\(a_i\),那么这种物品的生成函数\(G(i)=\sum_{j=0}^{\infty}x^{ ...
- 洛谷P4389 付公主的背包 [生成函数,NTT]
传送门 同样是回过头来发现不会做了,要加深一下记忆. 思路 只要听说过生成函数的人相信第一眼都可以想到生成函数. 所以我们要求 \[ ans=\prod \sum_n x^{nV}=\prod \fr ...
- [洛谷P4389]付公主的背包
题目大意:有$n(n\leqslant10^5)$种物品,第$i$个物品体积为$v_i$,都有$10^5$件.给定$m(m\leqslant10^5)$,对于$s\in [1,m]$,请你回答用这些商 ...
- LuoguP4389 付公主的背包【生成函数+多项式exp】
题目背景 付公主有一个可爱的背包qwq 题目描述 这个背包最多可以装10^5105大小的东西 付公主有n种商品,她要准备出摊了 每种商品体积为Vi,都有10^5105件 给定m,对于s\in [1,m ...
- Solution -「洛谷 P4389」付公主的背包
\(\mathcal{Description}\) Link. 容量为 \(n\),\(m\) 种物品的无限背包,求凑出每种容量的方案数,对 \(998244353\) 取模. \(n,m ...
- luogu4389 付公主的背包
题目链接:洛谷 题目大意:现在有$n$个物品,每种物品体积为$v_i$,对任意$s\in [1,m]$,求背包恰好装$s$体积的方案数(完全背包问题). 数据范围:$n,m\leq 10^5$ 这道题 ...
随机推荐
- Elasticsearch学习笔记(七)document小结
一.生成document id 1.自动生成document id 自动生成的id,长度为20个字符,URL安全,base64编码,GUID,分布式系统并行生成时不可能 ...
- 把jmeter获取到的信息存到本地文件
1.jmeter使用正则表达式提取器,获取到响应信息,把获取到的响应信息写到本地文件 2.添加后置Bean Shell ,写入以下脚本 3.打开本地文件查看,写入成功 脚本内容如下: FileWrit ...
- T-SQL语言基础(2)之SQL Server体系结构
SQL Server 体系结构 SQL Server 实例 SQL Server 实例是指安装的一个 SQL Server 数据库引擎/服务.在同一台计算机上可以安装 SQL Server 的多个实例 ...
- hystrix参数使用方法
hystrix+feign+ribbon,但是可能很多人都知道hystrix还有线程隔离,信号量隔离,等等各种参数配置,在这几就记录下hystrix的参数, 一.hystrix参数使用方法 通过注解@ ...
- 【Python】This inspection detects names that should resolve but don't. Due to dynamic dispatch and duck
情况一:导包import时发生错误,请参考这两位 https://blog.csdn.net/zhangyu4863/article/details/80212068https://www.cnblo ...
- 【QT】Installer requires Xcode Version 5.0.0 for Qt download if toolchain not found
When I install QT in MacOS 11.3.6, it prompts I need to install xcode then I install xcode but it wa ...
- 【LeetCode每天一题】Set Matrix Zeroes(设置0矩阵)
Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in-place. Exampl ...
- 使用TCP通信文件上传
客服端读取本地文件,吧文件上传到服务器,服务器在吧上传的文件保存到服务器硬盘上方法分析1:客户端使用本地字节输入流读取要上传的文件 2:客户端使用网络字节输出流,吧读取到的文件上传到服务器 3:服务器 ...
- Centos7 Lnmp的环境搭建
centos 版本 [root@localhost ~]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) 关闭防火墙 sy ...
- java操作git简单实现
记录瞬间 import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ListBranchCommand; import org.ecli ...