【洛谷5月月赛】玩游戏(NTT,生成函数)

题面

Luogu

题解

看一下要求的是什么东西

\((a_x+b_y)^i\)的期望。期望显然是所有答案和的平均数。

所以求出所有的答案就在乘一个逆元就好了。

现在考虑怎么算上面那个东西。

对于单个的计算,我们可以用二项式定理直接展开

得到

\[\begin{aligned}\sum(a+b)^k&=\sum\sum_{i=0}^kC_k^ia^ib^{k-i}\\&=\sum_{i=0}^kC_k^i(\sum a^i)(\sum b^{k-i})\\&=\sum_{i=0}^k\frac{k!}{i!(k-i)!}(\sum a^i)(\sum b^{k-i})\\&=k!\sum_{i=0}^k\frac{\sum a^i}{i!}\frac{\sum b^{k-i}}{(k-i)!} \end{aligned}
\]

这样就是很明显的卷积的形式了。

现在考虑怎么计算\(\sum a^i\),

构造\(G(x)=\prod_{i=1}^n(1+a_ix)\)

然后对于\(G(x)\)求\(ln\),再给第\(i\)项乘上\(i\)就好了。

为什么?

因为是乘积的形式,所以\(ln\)之后等价于对于所有东西都先\(ln\)在求和

所以考虑一下单个的\(ln\)值是什么,然后有\(ln'(A(x))=\frac{A'(x)}{A(x)}\)

这个手动用生成函数玩一下就知道了为啥了。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MOD 998244353
#define MAX 888888
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int fpow(int a,int b)
{
int s=1;
while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}
return s;
}
int r[MAX],W[MAX];
void NTT(int *P,int len,int opt)
{
int N,l=0;
for(N=1;N<len;N<<=1)++l;
for(int i=0;i<N;++i)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
for(int i=0;i<N;++i)if(i<r[i])swap(P[i],P[r[i]]);
for(int i=1;i<N;i<<=1)
{
int w=fpow(3,(MOD-1)/(i<<1));W[0]=1;
for(int k=1;k<i;++k)W[k]=1ll*W[k-1]*w%MOD;
for(int p=i<<1,j=0;j<N;j+=p)
for(int k=0;k<i;++k)
{
int X=P[j+k],Y=1ll*P[i+j+k]*W[k]%MOD;
P[j+k]=(X+Y)%MOD;P[i+j+k]=(X+MOD-Y)%MOD;
}
}
if(opt==-1)
{
reverse(&P[1],&P[N]);
for(int i=0,inv=fpow(N,MOD-2);i<N;++i)P[i]=1ll*P[i]*inv%MOD;
}
}
int n,m,t[MAX];
int S1[MAX],S2[MAX];
int inv[MAX];
int F[MAX],P[MAX];
int jc[MAX],jcinv[MAX];
int tmp[50][MAX],St[50],top;
void Solve(int l,int r,int *P,int *t)
{
if(l==r){P[1]=t[l];P[0]=1;return;}
int mid=(l+r)>>1,N,ls=St[top--];
Solve(l,mid,tmp[ls],t);
int rs=St[top--];
Solve(mid+1,r,tmp[rs],t);
for(N=1;N<=r-l+1;N<<=1);
NTT(tmp[ls],N,1);NTT(tmp[rs],N,1);
for(int i=0;i<N;++i)P[i]=1ll*tmp[ls][i]*tmp[rs][i]%MOD;
NTT(P,N,-1);
St[++top]=ls;St[++top]=rs;
for(int i=0;i<N;++i)tmp[ls][i]=tmp[rs][i]=0;
}
namespace Poly
{
int A[MAX],B[MAX];
void Inv(int *a,int *b,int len)
{
if(len==1){b[0]=fpow(a[0],MOD-2);return;}
Inv(a,b,len>>1);
for(int i=0;i<len;++i)A[i]=a[i],B[i]=b[i];
NTT(A,len<<1,1);NTT(B,len<<1,1);
for(int i=0;i<len<<1;++i)A[i]=1ll*A[i]*B[i]%MOD*B[i]%MOD;
NTT(A,len<<1,-1);
for(int i=0;i<len;++i)b[i]=(b[i]+b[i])%MOD;
for(int i=0;i<len;++i)b[i]=(b[i]+MOD-A[i])%MOD;
for(int i=0;i<len<<1;++i)A[i]=B[i]=0;
}
void Dao(int *a,int *b,int len)
{
for(int i=1;i<len;++i)b[i-1]=1ll*a[i]*i%MOD;
b[len]=b[len-1]=0;
}
void Jifen(int *a,int *b,int len)
{
for(int i=1;i<len;++i)b[i]=1ll*a[i-1]*inv[i]%MOD;
b[0]=0;
}
int C[MAX],D[MAX];
void ln(int *a,int *b,int len)
{
memset(C,0,sizeof(C));memset(D,0,sizeof(D));
Dao(a,C,len);Inv(a,D,len);
NTT(C,len<<1,1);NTT(D,len<<1,1);
for(int i=0;i<len<<1;++i)C[i]=1ll*C[i]*D[i]%MOD;
NTT(C,len<<1,-1);Jifen(C,b,len);
}
int E[MAX],G[MAX];
void Exp(int *a,int *b,int len)
{
if(len==1){b[0]=1;return;}
Exp(a,b,len>>1);ln(b,E,len);
for(int i=0;i<len;++i)E[i]=(MOD-E[i]+a[i])%MOD;E[0]=(E[0]+1)%MOD;
for(int i=0;i<len;++i)G[i]=b[i];
NTT(E,len<<1,1);NTT(G,len<<1,1);
for(int i=0;i<len<<1;++i)E[i]=1ll*E[i]*G[i]%MOD;
NTT(E,len<<1,-1);
for(int i=0;i<len;++i)b[i]=E[i];
for(int i=0;i<len<<1;++i)E[i]=G[i]=0;
}
}
int A[MAX],B[MAX],K;
int SA[MAX],SB[MAX];
int main()
{
n=read();m=read();
for(int i=1;i<=n;++i)A[i]=read();
for(int i=1;i<=m;++i)B[i]=read();
K=read();
inv[0]=inv[1]=1;
int len;for(len=1;len<=max(n,m)+K;len<<=1);
for(int i=2;i<(len<<1);++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
for(int i=0;i<50;++i)St[++top]=i;Solve(1,n,S1,A);Poly::ln(S1,SA,len);top=0;
for(int i=0;i<50;++i)St[++top]=i;Solve(1,m,S2,B);Poly::ln(S2,SB,len);top=0;
for(int i=0;i<len;++i)SA[i]=1ll*SA[i]*i%MOD;
for(int i=0;i<len;i+=2)SA[i]=(MOD-SA[i])%MOD;
for(int i=0;i<len;++i)SB[i]=1ll*SB[i]*i%MOD;
for(int i=0;i<len;i+=2)SB[i]=(MOD-SB[i])%MOD;
SA[0]=n;SB[0]=m;jc[0]=jcinv[0]=1;
for(int i=1;i<len;++i)jc[i]=1ll*i*jc[i-1]%MOD;
for(int i=1;i<len;++i)jcinv[i]=1ll*jcinv[i-1]*inv[i]%MOD;
memset(A,0,sizeof(A));memset(B,0,sizeof(B));
for(int i=0;i<=K;++i)A[i]=1ll*SA[i]*jcinv[i]%MOD;
for(int i=0;i<=K;++i)B[i]=1ll*SB[i]*jcinv[i]%MOD;
for(len=1;len<=K+K;len<<=1);
NTT(A,len,1);NTT(B,len,1);
for(int i=0;i<len;++i)A[i]=1ll*A[i]*B[i]%MOD;
NTT(A,len,-1);
for(int i=1,inv=fpow(1ll*n*m%MOD,MOD-2);i<=K;++i)
{
int ans=1ll*A[i]*jc[i]%MOD*inv%MOD;
printf("%d\n",ans);
}
return 0;
}

【洛谷5月月赛】玩游戏(NTT,生成函数)的更多相关文章

  1. 洛谷4月月赛R2

    洛谷4月月赛R2 打酱油... A.koishi的数学题  线性筛约数和就可以\(O(N)\)了... #include <iostream> #include <cstdio> ...

  2. 洛谷3月月赛 R1 Step! ZERO to ONE

    洛谷3月月赛 R1 Step! ZERO to ONE 普及组难度 290.25/310滚粗 t1 10分的日语翻译题....太难了不会... t2 真·普及组.略 注意长为1的情况 #include ...

  3. 【LGR-054】洛谷10月月赛II

    [LGR-054]洛谷10月月赛II luogu 成功咕掉Codeforces Round #517的后果就是,我\(\mbox{T4}\)依旧没有写出来.\(\mbox{GG}\) . 浏览器 \( ...

  4. 【LGR-051】洛谷9月月赛

    [LGR-051]洛谷9月月赛 luogu 签到题 description 给出\(K\)和质数\(m\),求最小的\(N\)使得\(111....1\)(\(N\)个\(1\))\(\equiv k ...

  5. 「LGR-049」洛谷7月月赛 D.Beautiful Pair

    「LGR-049」洛谷7月月赛 D.Beautiful Pair 题目大意 : 给出长度为 \(n\) 的序列,求满足 \(i \leq j\) 且 $a_i \times a_j \leq \max ...

  6. 洛谷9月月赛round2

    洛谷9月月赛2 t1 题意:懒得说了 分析:模拟 代码: program flag; var a:..,..]of char; n,i,m,j,x,y,ans,k:longint; begin ass ...

  7. 「P4996」「洛谷11月月赛」 咕咕咕(数论

    题目描述 小 F 是一个能鸽善鹉的同学,他经常把事情拖到最后一天才去做,导致他的某些日子总是非常匆忙. 比如,时间回溯到了 2018 年 11 月 3 日.小 F 望着自己的任务清单: 看 iG 夺冠 ...

  8. 「P4994」「洛谷11月月赛」 终于结束的起点(枚举

    题目背景 终于结束的起点终于写下句点终于我们告别终于我们又回到原点…… 一个个 OIer 的竞赛生涯总是从一场 NOIp 开始,大多也在一场 NOIp 中结束,好似一次次轮回在不断上演.如果这次 NO ...

  9. 「LuoguP4995」「洛谷11月月赛」 跳跳!(贪心

    题目描述 你是一只小跳蛙,你特别擅长在各种地方跳来跳去. 这一天,你和朋友小 F 一起出去玩耍的时候,遇到了一堆高矮不同的石头,其中第 ii 块的石头高度为 h_ihi​,地面的高度是 h_0 = 0 ...

随机推荐

  1. 51Nod 1668 非010串

    这是昨天上课ChesterKing dalao讲线代时的例题 当时看到这道题就觉得很水,记录一下后面两位的情况然后讨论一下转移即可 由于之前刚好在做矩阵题,所以常规的矩阵快速幂优化也很简单 好我们开始 ...

  2. [Oracle][PDB]PDB restore/recover 过程记录

    友人给的PDB restore / recover 的过程. 实际上会创建一个辅助Instance,然后抽取出PDB,进行恢复. (10:31:59) frank.yan: [Administrato ...

  3. STM32 M3内核的位带操作原理及步骤

    STM32 M3内核的位带操作原理及步骤 一.位带操作有什么用?什么是位带操作 位带操作的作用:可以实现对某一GPIO口寄存器(或SRAM内存中)的某一bit位直接写0或1,达到控制GPIO口输出(或 ...

  4. Jlink使用技巧之烧写SPI Flash存储芯片

    前言 大多数玩单片机的人都知道Jlink可以烧写Hex文件,作为ARM仿真调试器,但是知道能烧写SPI Flash的人应该不多,本篇文章将介绍如何使用JLink来烧写或者读取SPI Flash存储器, ...

  5. python中使用pymongo操作mongo

    MongoDB是由C++语言编写的非关系型数据库,是一个基于分布式文件存储的开源数据库系统,其内容存储形式类似JSON对象,它的字段值可以包含其他文档.数组及文档数组,非常灵活.在这一节中,我们就来看 ...

  6. GeForce Experience关闭自动更新

    GeForce Experience驱动更新很烦,而且有时更新后就打不开了,找到种方法关闭更新 1.安装并登陆 2.打开 C:\ProgramData\NVIDIA Corporation 3.进入D ...

  7. react/React Native 在 import 导入时,有的带花括号{},有的不带原理解析

    在使用import引用模块时,如何正确使用{} 例如:有两个文件,home.js.user.js 一:不使用{}: 当需要在home.js中引入user.js的时候 //home.js 文件中impo ...

  8. 对MSF八个原则的思考

    第一个原则,也是MSF中最基础的一个原则,推动信息共享与沟通.这个原则的一个特点是,对于团队成员的所有工作,都会被记录下来,包括走了弯路的.出现bug但已调试解决的部分.对于新加入团队的成员或者以前没 ...

  9. Week 3 结对编程

    Group: 杜正远 潘礼鹏 结对编程: 优点: 集体荣誉感.你们已经是一个集体了,一定得为对方着想负责. 1.看对方的代码,彼此会互相学习到一些奇妙的方法. 2.结对编程能把两个事情分开,降低复杂度 ...

  10. ELF分析 实践

    分析ELF文件: 首先编写一个.c文件,并使用gcc -c xx.c -o xx.o 对其进行编译. 我在这个实践中是ELF_1.o文件. 接下来输入ls -l ELF_1.o 查看重定位文件的信息. ...