---
# System prepended metadata

title: ABC_280_E - Critical Hit
tags: [題單]

---

---
title: ABC_280_E - Critical Hit
tags: 題單
disqus: hackmd
---

# ABC_280_E - Critical Hit

[題目連結](https://atcoder.jp/contests/abc280/tasks/abc280_e)

題目大意：
原來有個數 $N$，每次操作有 $1-\frac{p}{100}$ 的機會少 $1$，$\frac{p}{100}$ 的機會少 $2$
請問使 $N$ 變為 $0$ 的操作次數期望值是多少

注意事項：
- 請將答案$\mod 998244353$ 後輸出


## 解法

[官方解答](https://atcoder.jp/contests/abc280/editorial/5342)

人生第一次自己想出期望值 DP 的解法 ~~雖然這題很簡單~~
再加上人生第一次用上費馬小定理

~~兩個人生的第一次都奉獻給它了~~
所以寫個文章來紀念一下

### DP 轉移式

因為會改變的是數字，所以我用**到每個數字的期望步驟數**來做 DP

從操作的規則來看可以知道一個數 $N$ 的轉移點是 $N-1$ 和 $N-2$
而 $N = 1$ 時必定會在下一步變成 $0$

所以經過一陣通靈，得到了下面的轉移式

$\begin{cases}
dp_0 = 0 \\
dp_1 = 1 \\
dp_i = 1 + dp_{i-1} \times (1-\frac{p}{100}) + dp_{i-2} \times \frac{p}{100} \  (2 \le i \le N)
\end{cases}$

只要跟著做就行了

### 關於 mod

可想而知這樣 DP 出來的數會很大
所以題目要我們$\mod 998244353$ 後再輸出

但我們在計算 DP 中會用到除法
而 mod 運算中無法定義除法
所以需要用到[模反元素](https://zh.wikipedia.org/zh-tw/模反元素)來代替除法

模反元素大概的定義：
$a \equiv a^{-1} \mod P$
其中 $a$ 與 $a^{-1}$ 互為模反元素且 $a$ 與 $P$ 互質

而 mod 運算中的除法就需要改成乘以模反元素

所以在 mod 質數的情況下我們可以任何數做除法（也就是乘以模反元素）
因為質數與自己和 1 以外比自己小的任何數都互質

### 這題的 mod

這題 mod 的數為質數，所以不需要擔心不能除的問題

接著看一下運算式，我們從頭到尾都只有除 100
所以我們只需要把 100 的模反元素找出來就可以了

### 找模反元素

模反元素有多種找法，我這裡用的是[費馬小定理](https://zh.wikipedia.org/zh-tw/费马小定理)求 $a^{P-2}$ 也就是 $a^{998244351}$

使用[快速冪](https://zh.wikipedia.org/zh-tw/平方求幂)來求解可以得到 $100^{-1} = 828542813 \mod 998244353$

然後在每個除以 100 的地方都改成乘以 828542813 就大功告成了

這裡附上我寫的解：
```cpp
#include <bits/stdc++.h>
 
using namespace std;
#define ll long long
#define N 200005
#define oo 0x3f3f3f3f
#define ool 0x3f3f3f3f3f3f3f3f
#define P (int)(998244353)
#define F first
#define S second
#define pii pair<int, int>
#define lowbit(x) (x&-x)

ll inv_ten = 828542813;

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);

	int n;
	ll p;
	cin >> n >> p;

	ll dp[N] = {0};
	dp[1] = 1;
	for(int i=2; i<=n; i++){
		dp[i] = 1;
		dp[i] += (dp[i-1] * (100 - p) % P) * inv_ten % P;
		dp[i] += (dp[i-2] * p % P) * inv_ten % P;
		if(dp[i] > P)
			dp[i] %= P;
	}
	cout << dp[n] << endl;

		
    return 0;
}
```



