Luogu P4705 玩游戏
题目描述
Alice 和 Bob 又在玩游戏。
对于一次游戏,首先 Alice 获得一个长度为 的序列 ,Bob 获得一个长度为 的序列 bb。之后他们各从自己的序列里随机取出一个数,分别设为 ,定义这次游戏的 次价值为。
由于他们发现这个游戏实在是太无聊了,所以想让你帮忙计算对于 一次游戏 次价值的期望是多少。
由于答案可能很大,只需要求出模 下的结果即可。
输入输出格式
输入格式:
第一行两个整数 ,分别表示 Alice 和 Bob 序列的长度。
接下来一行 个数,第 个数为 ,表示 Alice 的序列。
接下来一行 个数,第 个数为 ,表示 Bob 的序列。
接下来一行一个整数 ,意义如上所述。
输出格式:
共 行,第 行表示一次游戏 次价值的期望。
输入输出样例
输入样例#1:
复制
1 1
1
2
3
输出样例#1:
复制
3
9
27
输入样例#2:
复制
2 8
764074134 743107904
663532060 183287581 749169979 7678045 393887277 27071620 13482818 125504606
6
输出样例#2:
复制
774481679
588343913
758339354
233707576
36464684
461784746
神仙题啊!!
前置知识:
生成函数。
Taylor展开。
NTT。
多项式求。
次价值得期望就是。
用二项式定理将分子展开:
考虑将展开:
我们设:
答案就是
问题的关键就在于预处理出。
预处理出这个多项式的方法是一个经典套路(根本不会)。
设
这
个
可
以
用
分
治
求
出
。
通过的系数可以预处理出A和B。
解释一下,最后一步变换:
根据Taylor展开:
求导如下:
复合函数求导遵循链式法则:
于是:
我们再处展开,也就是令
得到:
于是我们求出然后就可以用第项得系数来算出和。
代码(算的逆元的时候乘爆了,调了一晚上):
include<bits/stdc++.h>
define ll long long
define N 300005
define mod 998244353
using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch'-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return xf;}
ll n,m;
int t;
ll a[N],b[N];
ll fac[N<<2],inv[N<<2];
ll ksm(ll t,ll x) {
ll ans=1;
for(;x;x>>=1,t=tt%mod)
if(x&1) ans=ans*t%mod;
return ans;
}
ll Mod(ll a) {
if(a<0) return a+mod;
if(a>=mod) return a-mod;
return a;
}
int rev[N<<2];
void NTT(ll *a,int d,int flag) {
static const ll G=3;
int n=1<<d;
for(int i=0;i<n;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<d-1);
for(int i=0;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int s=1;s<=d;s++) {
int len=1<<s,mid=len>>1;
ll w=flag1?ksm(G,(mod-1)/len):ksm(G,mod-1-(mod-1)/len);
for(int i=0;i<n;i+=len) {
ll t=1;
for(int j=0;j<mid;j++,t=tw%mod) {
ll u=a[i+j],v=a[i+j+mid]t%mod;
a[i+j]=Mod(u+v);
a[i+j+mid]=Mod(u-v+mod);
}
}
}
if(flag-1) {
ll inv=ksm(n,mod-2);
for(int i=0;i<n;i++) a[i]=a[i]*inv%mod;
}
}
struct poly {
ll g[N<<2],f[N<<2];
ll a[N<<2],ans[N<<2];
void solve(int l,int r) {
if(lr) return ;
int len=r-l+1,mid=l+r>>1;
solve(l,mid),solve(mid+1,r);
int d=ceil(log2(len+1));
for(int i=0;i<(1<<d);i++) g[i]=f[i]=0;
g[0]=f[0]=1;
for(int i=l;i<=mid;i++) f[i-l+1]=a[i];
for(int i=mid+1;i<=r;i++) g[i-mid]=a[i];
NTT(f,d,1),NTT(g,d,1);
for(int i=0;i<(1<<d);i++) f[i]=f[i]g[i]%mod;
NTT(f,d,-1);
for(int i=l;i<=r;i++) a[i]=f[i-l+1];
}
ll inv[N<<2],A[N<<2];
void Inverse(ll a,int d,ll f) {
f[0]=ksm(a[0],mod-2);
for(int s=1;s<=d;s++) {
int len=1<<s,Len=len<<1;
for(int i=0;i<len;i++) A[i]=a[i],A[i+len]=0;
NTT(A,s+1,1),NTT(f,s+1,1);
for(int i=0;i<Len;i++) f[i]=(2f[i]-f[i]f[i]%modA[i]%mod+mod)%mod;
NTT(f,s+1,-1);
for(int i=len;i<Len;i++) f[i]=0;
}
}
void DER(ll a,int n) {
for(int i=0;i<n;i++) a[i]=a[i+1](i+1)%mod;
a[n]=a[n-1]=0;
}
void INT(ll a,int n) {
for(int i=n-1;i>=0;i--) a[i+1]=a[i]ksm(i+1,mod-2)%mod;
a[0]=0;
}
void Ln(ll *a,int d,ll f) {
Inverse(a,d,inv);
DER(a,1<<d);
NTT(inv,d+1,1),NTT(a,d+1,1);
for(int i=0;i<(1<<d+1);i++) f[i]=inv[i]a[i]%mod;
NTT(f,d+1,-1);
INT(f,1<<d);
}
void mian(int n,int lim,ll *orig,ll f) {
for(int i=1;i<=n;i++) a[i]=orig[i];
solve(1,n);
int d=ceil(log2(lim));
a[0]=1;
Ln(a,d,ans);
for(int i=1;i<=(1<<d);i++) {
f[i]=ans[i];
f[i]=f[i]::inv[i-1]%mod;
if(!(i&1)) f[i]=(mod-f[i])%mod;
}
}
}pre[2];
ll A[N<<2],B[N<<2];
int main() {
n=Get(),m=Get();
for(int i=1;i<=n;i++) a[i]=Get();
for(int i=1;i<=m;i++) b[i]=Get();
t=Get();
fac[0]=1;
for(int i=1;i<=t;i++) fac[i]=fac[i-1]*i%mod;
inv[t]=ksm(fac[t],mod-2);
for(int i=t-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
int lim=max(n,m)+t;
pre[0].mian(n,lim,a,A);
pre[1].mian(m,lim,b,B);
int d=ceil(log2(t*2));
A[0]=n,B[0]=m;
for(int i=t+1;i<(1<<d);i++) A[i]=B[i]=0;
NTT(A,d,1),NTT(B,d,1);
for(int i=0;i<(1<<d);i++) A[i]=A[i]*B[i]%mod;
NTT(A,d,-1);
ll invnm=ksm(1ll*n*m%mod,mod-2);
for(int i=1;i<=t;i++) {
cout<<fac[i]*A[i]%mod*invnm%mod<<"\n";
}
return 0;
}
Luogu P4705 玩游戏的更多相关文章
- 洛谷 P4705 玩游戏 解题报告
P4705 玩游戏 题意:给长为\(n\)的\(\{a_i\}\)和长为\(m\)的\(\{b_i\}\),设 \[ f(x)=\sum_{k\ge 0}\sum_{i=1}^n\sum_{j=1}^ ...
- Luogu 4705 玩游戏
看见这个题依稀想起了$5$月月赛时候的事情,到现在仍然它感觉非常神仙. 游戏$k$次价值的期望答案 $$ans_k = \frac{1}{nm}\sum_{i = 1}^{n}\sum_{j = 1} ...
- P4705 玩游戏
思路 超级麻烦... 写了一堆最后常数太大T飞了... 真的难受 发现solve函数可以不用把下一层复制上来,直接传指针就可以,下次再说写不写叭 思路 \[ ans_k=\sum_{i=1}^n\su ...
- 洛谷P4705 玩游戏 [生成函数,NTT]
传送门 这是两个月之前写的题,但没写博客.现在回过头来看一下发现又不会了-- 还是要写博客加深记忆. 思路 显然期望可以算出总数再乘上\((nm)^{-1}\). 那么有 \[ \begin{alig ...
- [洛谷P4705]玩游戏
题目大意:对于每个$k\in[1,t]$,求:$$\dfrac{\sum\limits_{i=1}^n\sum\limits_{j=1}^m(a_i+b_j)^k}{nm}$$$n,m,t\leqsl ...
- 洛谷 P4705 玩游戏
题目分析 题目要求的是: \[ \sum_{i=1}^n\sum_{j=1}^m(a_i+b_j)^x(x\in [1,T]) \] 利用二项式定理化式子, \[ \begin{aligned} &a ...
- 洛谷P4705 玩游戏(生成函数+多项式运算)
题面 传送门 题解 妈呀这辣鸡题目调了我整整三天--最后发现竟然是因为分治\(NTT\)之后的多项式长度不是\(2\)的幂导致把多项式的值存下来的时候发生了一些玄学错误--玄学到了我\(WA\)的点全 ...
- 【洛谷5月月赛】玩游戏(NTT,生成函数)
[洛谷5月月赛]玩游戏(NTT,生成函数) 题面 Luogu 题解 看一下要求的是什么东西 \((a_x+b_y)^i\)的期望.期望显然是所有答案和的平均数. 所以求出所有的答案就在乘一个逆元就好了 ...
- [luogu]P1070 道路游戏[DP]
[luogu]P1070 道路游戏 题目描述小新正在玩一个简单的电脑游戏.游戏中有一条环形马路,马路上有 n 个机器人工厂,两个相邻机器人工厂之间由一小段马路连接.小新以某个机器人工厂为起点,按顺时针 ...
随机推荐
- php持续推送信息到客户端的方法
<?php set_time_limit(0); $i=1; while($i++) { echo $i,'<br />'; ob_flush();//冲刷出(送出)输出缓冲区中的内 ...
- 自己写的thinkphp自动生成类
模型类:CqhModel.class.php <?php namespace Cqh\Model; use Think\Model; class CqhModel extends Model { ...
- rtsp信令交互流程
- shell | {}和()
执行 bash -n xx.sh用于检测脚本语法是否有错误 bash -x xx.sh用于追踪执行 ${var} 用于限定变量名称的范围,并且支持通配符 $(cmd) shell会先执行括号的cmd, ...
- MySQL之视图、触发器、事务、存储、函数、流程控制
一.视图 视图就是一个虚拟表,我们把复杂的sql语句后看到的虚拟表封装起来,给他取个名字,当我们下次使用的时候,就不用再去写复杂的sql语句,直接调用封装后的视图名字,就可以得到我们想要的表,然后就可 ...
- jquery 获得下拉框的值《转》
获取Select : 获取select 选中的 text : $("#ddlRegType").find("option:selected").text(); ...
- Redis入门 -- Redis安装与配置
Redis入门 -- Redis安装与配置 Redis的安装 Redis的安装,我这里使用的是虚拟机. 为了让主机和虚拟机之间可以顺利通信,按照以下步骤进行: 1. 将网络连接模式改为桥接 2. re ...
- 【Java并发编程】9、非阻塞同步算法与CAS(Compare and Swap)无锁算法
转自:http://www.cnblogs.com/Mainz/p/3546347.html?utm_source=tuicool&utm_medium=referral 锁(lock)的代价 ...
- java_查找里程
题目内容: 下图为国内主要城市之间的公路里程: 你的程序要读入这样的一张表,然后,根据输入的两个城市的名称,给出这两个城市之间的里程. 注意:任何两个城市之间的里程都已经给出,不需要计算经第三地中转. ...
- springMVC 拦截器源码解析
前言:这两天学习了代理模式,自然想到了 springmvc 的 aop 使用的就是动态代理,拦截器使用的就是 jdk 的动态代理.今天看了看源码,记录一下.转载请注明出处:https://www.cn ...