洛谷十月月賽T2[深海少女與胖頭魚]小結
題面
洛谷十月月賽II T2
深海少女與胖頭魚
總共有
n
n
n 條帶 「聖盾」的「胖頭魚」和
m
m
m 條不帶聖盾的胖頭魚,每次等概率對一條存活的胖頭魚造成「劇毒」傷害。
現在想知道,期望造成多少次傷害可以殺死全部胖頭魚?
答案對 998244353 998244353 998244353 取模。
「聖盾」:當擁有聖盾的胖頭魚受到傷害時,免疫這條魚所受到的本次傷害。免疫傷害後,聖盾被破壞。
「胖頭魚」:在一條胖頭魚的聖盾被破壞後,給予其他所有沒有死亡且沒有聖盾的胖頭魚聖盾。
「劇毒」:立即殺死沒有聖盾的胖頭魚。
輸入:2 1 輸出:8
輸入:10 10 輸出:499122389
輸入:10 0 輸出:65
輸入:2 0 輸出:5
前置知識
數學期望
※離散型:
如果隨機變數只取得有限個值或無窮能按一定次序一一列出,其值域為一個或若干個有限或無限區間,這樣的隨機變數稱為離散型隨機變數。
離散型隨機變數的一切可能的取值 x i x_i xi與對應的概率 p ( x i ) p(x_i) p(xi)乘積之和稱為該離散型隨機變數的數學期望(若該求和絕對收斂),記為 E ( x ) E(x) E(x)。它是簡單算術平均的一種推廣,類似加權平均。
計算公式: E ( X ) = ∑ k = 1 ∞ x k p k E(X)=\sum_{k=1}^\infin x_kp_k E(X)=k=1∑∞xkpk
快速冪
求a的n次方,即求
a
n
=
a
∗
a
∗
a
∗
a
∗
.
.
.
∗
a
a^n=a*a*a*a*...*a
an=a∗a∗a∗a∗...∗a(
n
n
n個
a
a
a),但是當
a
,
n
a,n
a,n過大時,暴力的計算便不太適用了。
這時候我們就需要用到快速冪(<-標準解析)
快速冪,二進位制取冪(Binary Exponentiation,也稱平方法),是一個在 O ( l o g N ) O(logN) O(logN) 的時間內計算 a n a^n an 的小技巧,而暴力的計算需要 O ( N ) O(N) O(N) 的時間。而這個技巧也常常用在非計算的場景,因為它可以應用在任何具有結合律的運算中。
二進位制取冪的想法是,將取冪的任務按照指數的 二進位制表示 來分割成更小的任務
舉例:求
3
13
3^{13}
313
3
13
=
3
∗
3
∗
3
∗
3
∗
3
∗
3
∗
3
∗
3
∗
3
∗
3
∗
3
∗
3
∗
3
3^{13}=3*3*3*3*3*3*3*3*3*3*3*3*3
313=3∗3∗3∗3∗3∗3∗3∗3∗3∗3∗3∗3∗3
3 13 = 3 2 ∗ 3 2 ∗ 3 2 ∗ 3 2 ∗ 3 2 ∗ 3 2 ∗ 3 3^{13}=3^2*3^2*3^2*3^2*3^2*3^2*3 313=32∗32∗32∗32∗32∗32∗3
3 13 = 3 4 ∗ 3 4 ∗ 3 4 ∗ 3 3^{13}=3^4*3^4*3^4*3 313=34∗34∗34∗3
3 13 = 3 8 ∗ 3 4 ∗ 3 3^{13}=3^8*3^4*3 313=38∗34∗3
即
3 13 = 3 ( 1101 ) 2 = 3 8 ∗ 3 4 ∗ 3 3^{13}=3^{(1101)_2}=3^8*3^4*3 313=3(1101)2=38∗34∗3
程式碼如下
int power(int a,int b,int mod)//快速冪求a^b
{
int sum=1;//初始化答案
while(b)
{
if(b & 1)
sum=sum*a%mod;//b為奇數,就乘一個當前的a
b>>=1;//向下取整
a=a*a%mod;
}
return sum%mod;
}
逆元
本題中需要在除法中取模,但這在普通運算中不可行,那麼就要用到逆元的知識
逆元素(百度百科)
費馬小定理(OI-Wiki)
條件:
p
p
p為素數,
g
c
d
(
p
,
a
)
=
=
1
gcd(p,a)==1
gcd(p,a)==1
設
x
x
x為在(
m
o
d
mod
mod
p
p
p)條件下
a
a
a的逆元
a x ≡ 1 ( m o d p ) ① ax\equiv 1 (mod p)① ax≡1(modp)①
a p − 1 ≡ 1 ( m o d p ) a^{p-1}\equiv 1(modp) ap−1≡1(modp)
⇔ a ∗ a p − 2 ≡ 1 ( m o d p ) ② \Leftrightarrow a*a^{p-2}\equiv 1(modp)② ⇔a∗ap−2≡1(modp)②
由①②等價可得
x ≡ a p − 2 ( m o d p ) x\equiv a^{p-2}(modp) x≡ap−2(modp)
題解
分析
期望DP
由子任務 m = 0 m=0 m=0得到啟發,先對 m = 0 m=0 m=0情況分析
I.先處理只有帶聖盾胖頭魚的情況
令
f
u
f_u
fu表示
u
u
u條聖盾胖頭魚期望需要造成傷害的次數,
f
v
f_v
fv表示如圖所示中間狀態。首先我們需要消耗1次攻擊打破一個聖盾。
f u = f v + 1 f_u=f_v+1 fu=fv+1
那麼下一次攻擊會有兩種情況:
- 如果這次攻擊打到了沒有聖盾的那條魚,那麼這條魚死亡,狀態來到了
u
−
1
u-1
u−1條帶聖盾胖頭魚的狀態。事件概率為
1
u
\dfrac{1}{u}
u1。
f v 1 = 1 u ( f u − 1 + 1 ) f_{v1}=\dfrac{1}{u}(f_{u-1}+1) fv1=u1(fu−1+1)
- 如果這次攻擊打到了有聖盾的任意一條魚,那麼本質上是換了一條魚沒聖盾。事件概率為 u − 1 u \dfrac{u-1}{u} uu−1(這裡因為 f v f_v fv進入的狀態是已經破了一個聖盾的,所以要 − 1 -1 −1)。
f v 2 = u − 1 u ( f u + 1 − 1 ) = u − 1 u f u f_{v2}=\dfrac{u-1}{u}(f_u+1-1)=\dfrac{u-1}{u}f_u fv2=uu−1(fu+1−1)=uu−1fu
根據上面的分析,可以得出轉移方程:
f i = 1 i ( f i − 1 + 1 ) + i − 1 i f i + 1 f_i=\dfrac{1}{i}(f_{i-1}+1)+\dfrac{i-1}{i}f_i+1 fi=i1(fi−1+1)+ii−1fi+1
進一步化簡可得:
f i = f i − 1 + i + 1 f_i=f_{i-1}+i+1 fi=fi−1+i+1
f 1 = 2 f_1=2 f1=2
根據求和公式即可 O ( 1 ) O(1) O(1)求出 f i f_i fi:
f i = ∑ i = 1 n ( i + 1 ) = i ( i + 3 ) 2 f_i=\sum^{n}_{i=1}(i+1)=\dfrac{i(i+3)}{2} fi=i=1∑n(i+1)=2i(i+3)
得到了 f n f_n fn,接下來分析 m ≠ 0 m\ne0 m=0的情況
II.再處理加入不帶聖盾的胖頭魚
令 g i g_i gi為 n n n條帶盾魚, i i i條不帶聖盾的魚期望需要造成傷害的次數。
-
如果這次攻擊打到了沒有聖盾的胖頭魚,那麼這條魚死亡,進入 g i − 1 g_{i-1} gi−1的狀態。事件概率為 i n + i \dfrac{i}{n+i} n+ii。
-
如果這次攻擊打到了有聖盾的胖頭魚,那麼其他胖頭魚都會獲得聖盾,進入 f n + i − 1 f_{n+i}-1 fn+i−1的狀態(已經破了一個聖盾)。事件概率為 n n + i \dfrac{n}{n+i} n+in。
理解了上面的
f
i
f_i
fi,這段就很好理解了,不放圖了
歸納上式,得轉移方程:
g i = i n + i ( g i − 1 + 1 ) + n n + i f n + i g_i=\dfrac{i}{n+i}(g_{i-1}+1)+\dfrac{n}{n+i}f_{n+i} gi=n+ii(gi−1+1)+n+infn+i
答案即為 g m g_m gm。可以先求出 f i f_i fi,然後遞推計算 g m g_m gm。
AC Code
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define ll long long
#define MAXN 1000010
#define mod 998244353
ll n,m;
ll g[MAXN];
ll power(ll a,ll b)//快速冪求逆元
{
ll sum=1;
a%=mod;
while(b)
{
if(b&1)
sum=sum*a%mod;
b>>=1;
a=a*a%mod;
}
return sum%mod;
}
signed main(void)
{
scanf("%lld%lld",&n,&m);
ll p_2=power(2,mod-2)%mod;//2在(%mod)條件下的逆元
g[0]=( (p_2%mod * (n%mod))%mod * (n%mod+3)%mod )%mod;//好事多模
//g[0]即為全部都是有聖盾洗頭魚,初始化為g[0]=f[n];
for(ll i=1;i<=m;i++)
{
ll p_ni=power( (n%mod+i)%mod , mod-2 ) %mod;//(n+i)在(%mod)條件下的逆元
ll k_n=( (p_2 * (n%mod))%mod * (n%mod+i+3)%mod )%mod;
g[i]=( ( i * (g[i-1]%mod+1 )%mod * p_ni)%mod + k_n )%mod;
}
printf("%lld\n",g[m]%mod);//結束
return 0;
}
相關文章
- 洛谷11月月賽題解(A-C)
- 洛谷 P5595 歌唱比賽
- 洛谷P3853總結
- 洛谷
- 十年後,E胖與《以撒的結合》說再見
- 洛谷演算法競賽秋令營 - 基礎組/2024-T2總結演算法
- 洛谷團隊
- 洛谷 P3951 NOIP 2017 小凱的疑惑
- 洛谷P1422 小玉家的電費
- dfs與貪心演算法——洛谷5194演算法
- 洛谷死亡時間
- 洛谷P1786
- 洛谷 - P5369
- 洛谷P6786
- 洛谷P10725
- 洛谷P10693
- 洛谷 - P6190
- 洛谷——玩具謎題
- 英雄聯盟(洛谷)
- 洛谷 P6464 [傳智杯 #2 決賽] 傳送門
- 洛谷 P4173 殘缺的字串 卡常小記字串
- 洛谷網校學習
- 昨天放洛谷的圖
- 將洛谷私信接入WindowsWindows
- 洛谷 P10254 口吃
- 洛谷傻逼之處
- 洛谷八皇后問題
- 洛谷 P3958乳酪
- 【洛谷】【分支】月份天數
- [2024.11.11]NOIP模擬賽T2
- [題解][洛谷P1412] 經營與開發
- 洛谷 - 康託展開與逆康託展開
- 2018huaweictf7月月賽
- 洛谷P8208 [THUPC2022 初賽] 骰子旅行 題解 期望DP
- 洛谷 P11323 Happy CardAPP
- 洛谷P1784.數獨
- 洛谷題單指南-字串-Test字串
- 洛谷-P9574 題解