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$ 这道题 ...
随机推荐
- Linux 部署 xxl-job 注意问题
问题:Failed to create parent directories for [/data/applogs/xxl-job/xxl-job-admin.log][原因:权限不足] 启动终端: ...
- Spring Boot(三):AOP&日志操作&异常处理
一.AOP:HttpAspect.java 二.操作日志 在HttpAspect.java中调用org.slf4j.Logger.org.slf4j.LoggerFactory 三.异常处理 1.定义 ...
- @ResponseBody ResponseEntity
1.产生疑问 我们知道,如果在 Controller 的某个方法上加上 @ResponseBody 注解,那么你就能拿到 json 数据. 如果你只是知道这么用,那么你应该知道 ResponseBod ...
- Jenkins+Jmeter持续集成笔记(三:集成到Jenkins)
上一篇笔记中已经实现了通过ant工具执行Jmeter测试脚本,并输出html格式测试报告到指定目录. 在本章中,将尝试把这个过程丢进jenkins去执行. 1.Jenkins全局工具配置 登录jenk ...
- webpack(6)-模块热替代&tree shaking
模块热替换(hot module replacement 或 HMR) 模块热替换(hot module replacement 或 HMR)是 webpack 提供的最有用的功能之一.它允许在运行时 ...
- 【LeetCode每天一题】Rotate List(旋转链表)
Given a linked list, rotate the list to the right by k places, where k is non-negative. Example 1: I ...
- react github项目
https://github.com/bailicangdu/react-pxq 网址;https://github.com/bailicangdu/react-pxq
- Liunx系统升级自带的Python版本
一.查看系统信息 [root@localhost ~]# cat /etc/redhat-release CentOS release 6.4 (Final) [root@localhost ~]# ...
- Mac Pro 坑记录
第一天app store没法登陆,登陆后没有任何的反应,试过了改系统时间为一致.修改权限:sudo chmod -R 1777 /Users/Shared 都没什么用. 最后是终端运行: defaul ...
- 用一句sql语句更新两个表并可更新对应的字段的值
ACCESS 例子: insert into products (ProNumber,CASNumber,Cnname,Price,Enname,Baozhuang,Pinpai) select Pr ...