原文链接www.cnblogs.com/zhouzhendong/p/UOJ469.html

前言

clytql当场秒掉此题可惜不知道为什么fst了。

题解

考虑构建指数生成函数。

对于第 \(i\) 项,设其概率为 \(p_i\) (即题目中的 \(p_i / \sum_i p_i\)) 。构建指数生成函数:

\[f_i(x) = \sum_{j\geq 0, j\bmod 2 = s_i} p_i ^ j \frac {x^ j } { j !} \\ = \frac 1 2 (e ^ {p_i x } + (-1)^{s_i} e ^ {-p_i x })
\]

\(F(x) = \prod_i f_i(x) ,f(x) = \sum_{i} i! [x^i]F(x)\) 的 \(k\) 次项系数就是随机按 \(k\) 次开关到达指定状态的概率。

我们要求的是第一次到达指定状态的概率,所以我们需要将多项式 \(f(x)\) 除去"\(s_i\) 全为 0 时的多项式 \(g(x)\)"。

我们要算的是期望,所以我们要求的是

\[\frac{\rm d} { {\rm d} x } \left ( \frac {f(x)}{g(x)}\right )
\]

的各个系数之和。注意由于我们在求 \(f(x)\)、\(g(x)\) 时,就已经乘了一个阶乘将指数生成函数转化成对应的普通生成函数了。因为我们要除去的方案是从终止状态出发再回到终止状态的方案数(OGF),而不是在到达终止状态之前绕一圈的方案数(如果除以EGF)。

由于

\[\cfrac{\rm d} { {\rm d} x } \left ( \cfrac {f(x)}{g(x)} \right ) = \cfrac{f'(x) g(x) - g'(x) f(x) }{g ^ 2(x)}
\]

于是,我们来对每一个项考虑一下:

\[e ^ {kx} = \sum_{i\geq 0 } k ^ i \frac { x ^ i } { i ! }
\]

\[\sum_{i\geq 0} k ^ i x ^ i= \frac{1}{1 - kx}
\]

\[\frac{\rm d} { {\rm d} x } e ^ {kx} = k ^ 2 x e ^ {kx} = k ^ 2 x \sum_{i\geq 0 } k ^ i \frac { x ^ i } { i ! }
\]

\[\sum_{i\geq 1} k ^ {i+1} i \cdot x ^ i = \frac {k} { (1-kx) ^ 2}
\]

接下来我们把 \(x = 1\) 代入求解。

考虑到当 \(k = 1\) 时我们会得到 NAN,这导致了求解失败。

但是我们显然可以肯定答案不是 NAN。那么发生了什么?

之前提到,答案是

\[\cfrac{f'(x) g(x) - g'(x) f(x) }{g ^ 2(x)}
\]

我们只需要将分子分母上下同乘 \((1-kx) ^ 2\) 。

注意到 \(g^2(x)\) 里面有 \(\cfrac {1}{(1-kx) ^ 2}\) ,但是 $f'(x) g(x) $ 和 \(f(x)g'(x)\) 里面都有 \(\cfrac {1}{(1-kx) ^ 3}\) ,看起来似乎又是 NAN。注意到 $f'(x) g(x) $ 和 \(f(x)g'(x)\) 里面的 \(\cfrac {1}{(1-kx) ^ 3}\) 项在减法时抵消了,所以没有影响。

总时间复杂度 \(O(n \sum{p_ i} )\) 。

代码

#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof x)
#define For(i,a,b) for (int i=(a);i<=(b);i++)
#define Fod(i,b,a) for (int i=(b);i>=(a);i--)
#define fi first
#define se second
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define outval(x) cerr<<#x" = "<<x<<endl
#define outtag(x) cerr<<"---------------"#x"---------------"<<endl
#define outarr(a,L,R) cerr<<#a"["<<L<<".."<<R<<"] = ";\
For(_x,L,R)cerr<<a[_x]<<" ";cerr<<endl;
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef vector <int> vi;
LL read(){
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=105,S=1e5+10,mod=998244353;
int Pow(int x,int y){
int ans=1;
for (;y;y>>=1,x=(LL)x*x%mod)
if (y&1)
ans=(LL)ans*x%mod;
return ans;
}
void Add(int &x,int y){
if ((x+=y)>=mod)
x-=mod;
}
void Del(int &x,int y){
if ((x-=y)<0)
x+=mod;
}
int Add(int x){
return x>=mod?x-mod:x;
}
int Del(int x){
return x<0?x+mod:x;
}
int inv2=(mod+1)>>1;
int n;
int s[N],p[N],sum=0,invs;
int f[S],g[S],val[S],inv[N],O=5e4+5;
int ans=0;
void Get(int *a){
static int b[S];
For(i,-sum,sum){
a[i+O]=0;
val[i+O]=(LL)Del(i)*invs%mod;
inv[i+O]=Pow(Del(1-val[i+O]),mod-2);
}
a[0+O]=1;
For(i,1,n){
For(j,-sum,sum)
b[j+O]=0;
For(j,-sum,sum){
if (!a[j+O])
continue;
Add(b[j+p[i]+O],a[j+O]);
if (s[i])
Del(b[j-p[i]+O],a[j+O]);
else
Add(b[j-p[i]+O],a[j+O]);
}
For(j,-sum,sum)
a[j+O]=b[j+O];
}
}
int calc1(int *a,int *b){
// a' * b * (1 - x) ^ 2
int ans=0;
For(i,-sum,sum-1)
Add(ans,(LL)b[i+O]*inv[i+O]%mod);
ans=(LL)ans*a[sum+O]%mod;
return ans;
}
int calc2(int *a){
return (LL)a[sum+O]*a[sum+O]%mod;
}
int main(){
n=read();
For(i,1,n)
s[i]=read();
For(i,1,n)
p[i]=read(),sum+=p[i];
invs=Pow(sum,mod-2);
Get(f),clr(s),Get(g);
Add(ans,calc1(f,g));
Del(ans,calc1(g,f));
ans=(LL)ans*Pow(calc2(g),mod-2)%mod;
cout<<ans<<endl;
return 0;
}

UOJ#469. 【ZJOI2019】开关 生成函数的更多相关文章

  1. [ZJOI2019] 开关 (一种扩展性较高的做法)

    [ZJOI2019] 开关 (一种扩展性较高的做法) 题意: 有n个开关,一开始状态都为关闭.每次随机选出一个开关将其状态改变,选出第i个开关的概率为${ p_i \over \sum_{i=1}^n ...

  2. [ZJOI2019]开关(生成函数+背包DP)

    注:以下p[i]均表示概率 设F(x)为按i次开关后到达终止状态方案数的EGF,显然F(x)=π(ep[i]x/p+(-1)s[i]e-p[i]x/p)/2,然而方案包含一些多次到达合法方案的状态,需 ...

  3. [ZJOI2019]开关

    以下的方案数默认是带权方案数.设\(P=\sum_{i=1}^np_i\). 设\(F(x)\)为按\(i\)次开关后到达终止态的方案数的EGF,\(f\)为\(F\)的OGF,显然\(F(x)=\p ...

  4. 【UOJ#450】【集训队作业2018】复读机(生成函数,单位根反演)

    [UOJ#450][集训队作业2018]复读机(生成函数,单位根反演) 题面 UOJ 题解 似乎是\(\mbox{Anson}\)爷的题. \(d=1\)的时候,随便怎么都行,答案就是\(k^n\). ...

  5. Loj #3045. 「ZJOI2019」开关

    Loj #3045. 「ZJOI2019」开关 题目描述 九条可怜是一个贪玩的女孩子. 这天,她和她的好朋友法海哥哥去玩密室逃脱.在他们面前的是 \(n\) 个开关,开始每个开关都是关闭的状态.要通过 ...

  6. LOJ 3045: 洛谷 P5326: 「ZJOI2019」开关

    题目传送门:LOJ #3045. 题意简述 略. 题解 从高斯消元出发好像需要一些集合幂级数的知识,就不从这个角度思考了. 令 \(\displaystyle \dot p = \sum_{i = 1 ...

  7. UOJ#450. 【集训队作业2018】复读机 排列组合 生成函数 单位根反演

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ450.html 题解 首先有一个东西叫做“单位根反演”,它在 FFT 的时候用到过: $$\frac 1 ...

  8. uoj#335. 【清华集训2017】生成树计数(prufer序列+生成函数+多项式)

    传送门 好神仙的题目--又一次有了做一题学一堆的美好体验 据说本题有第二类斯特林数+分治\(FFT\)的做法,然而咱实在看不懂写的是啥,题解贴这里,有兴趣的可以自己去瞅瞅,看懂了记得回来跟咱讲讲 前置 ...

  9. 【loj3045】【ZJOI2019】开关

    题目 \(n\)个开关,一开始处于关闭状态,你需要将他们按成\(s\)状态,按成了之后就停止操作; 每次按下开关的i概率为\(\frac{p_i}{\sum_{i=1}^{n}p_i}\) ,问期望步 ...

随机推荐

  1. java之单元测试

    这篇主要简单讲下java的单元测试 目录结构如下: 如图,其中1是需要被测试的功能:2是测试模块:3是单元测试需要的引入包: 1. 功能模块1中 Calculator 的代码: package cn. ...

  2. Abp session和Cookie

    问道 面向Abp 在面向服务的时候,Session 干嘛用? 先把Session 的作用说了,但是在微服务环境下给忽略了,相当于忽略了核心. Session 只是个功能.就是根据Cookie 的Ses ...

  3. Angular2 环境的搭建

    在慕课网上学习angular,自己也动手做一做. 1:Nodejs的安装: https://nodejs.org/en/    下载--安装. (这一步中是将npm也安装了,记住自己选择的目录,我这里 ...

  4. NIO开发Http服务器(4):Response封装和响应

    最近学习了Java NIO技术,觉得不能再去写一些Hello World的学习demo了,而且也不想再像学习IO时那样编写一个控制台(或者带界面)聊天室.我们是做WEB开发的,整天围着tomcat.n ...

  5. Bootstrap 结合 PHP ,做简单的登录以及注册界面及功能

    登录实现 HTML代码 <div class="container"> <?php if (isset($error_msg)): ?> <div c ...

  6. css设置全局变量和局部变量

    在我们使用less或者sass时常常会使用到局部变量和全局变量,其实在我们使用css做开发时也可以定义全局变量和局部 变量来简化我们的开发效率,很简单也很实用:1.设置全局变量只需要在我们的根引用的c ...

  7. c#指定长度切割字符串,返回数组

    public List<string> subStringByCount(string text, int count) { ;//开始索引 ;//结束索引 double count_va ...

  8. TypeScript_泛型

    typescript 中很多地方都和 java 和 C# 相似,如果 有 java 和 C# 的同学入手typeScript 会简单很多, 下面这里使用代码来表示和展现泛型的定义和使用 //泛型:在类 ...

  9. curl 获取状态返回码

    [root@1708mode ~]# curl -o /dev/null -s -w "%{http_code}\n" baidu.com200 朋友问,就有了 wget 没学会& ...

  10. 【idea】scala&sbt+idea安装配置与测试

    一.IDEA安装 下载Community版的IDEA,Ultimate是免费试用版(相当于用到后面要给钱的) ideaIC-2019.2.3.tar.gz 解压IDEA: tar -zxvf idea ...