1. 程式人生 > 實用技巧 >Educational Codeforces Round 98 (Rated for Div. 2) D

Educational Codeforces Round 98 (Rated for Div. 2) D

Educational Codeforces Round 98 (Rated for Div. 2) D

大意

\(n+2\) 個村莊,按從 \(0\)\(n+1\) 標號。
村莊 \(1\)\(n\) 中允許安裝燈塔,每個村莊有二分之一的概率被安裝(互相獨立)。
現在,對於一種安裝方法,你需要給予每個燈塔能量 \(p\in N^{*}\)
如果一個位於 \(i\) 的燈塔被賦予了能量 \(p\) ,那麼,所有滿足 \(|c-i|<p\) 的標號為 \(c\) 的村莊將會被照亮。
一種給予能量的方法合法,當且僅當滿足以下兩個條件:
1,\(0\)\(n+1\) 不會被照亮。
2,其餘每個村莊都被照亮且僅被照亮一次。
問:
合法方案的概率是多少。
記答案為 \(\dfrac{x}{w}\)

,你需要輸出 \(x*w^{-1}\ mod\ 998244353\) 。其中 \(w^{-1}\) 代表 \(w\) 在模998244353下的逆元。

思路

方案數,不是組合就是dp。

原題可以等價轉化為以下表述:

選擇任意段長度為奇數的區間恰好總長為n

考慮 \(dp[i]\) 表示區間長度為 \(i\) 時的方案數

得到

\(dp[2n+1]=dp[2n]+dp[2n-2]+...+dp[0]\)

\(dp[2n+2]=dp[2n+1]+dp[2n-1]+...+dp[1]\)

奇數項方案數為前面所有偶數項之和

偶數項方案數為前面所有奇數項之和

每種方案概率相等

總情況數 \(2^n\)

求逆元計算即可

程式碼

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;

#define ll long long
#define ull unsigned long long
#define cint const int&
#define Pi acos(-1)

const int mod = 998244353;
const int inf_int = 0x7fffffff;
const ll inf_ll = 0x7fffffffffffffff;
const double ept = 1e-9;

int n;
ll to[200200];
ll dp[200200];

ll ksm(ll bs, int x) {
    ll ans=1;
    while(x) {
        if(x&1) ans = (ans*bs) % mod;
        bs = (bs*bs) % mod;
        x >>= 1;
    }
    return ans;
}

int main() {
    to[0] = 1;
    cin >> n;
    for(int i=1; i<=n; i++) to[i] = (to[i-1]*2) % mod;
    dp[0]=1, dp[1]=1, dp[2]=1;
    ll odd=1, eve=2;
    for(int i=3; i<=n; i++) {
        if(i&1) {
            dp[i] = eve;
            odd = (eve+odd) % mod;
        } else {
            dp[i] = odd;
            eve = (eve+odd) % mod;
        }
    }
    cout << (dp[n]*ksm(to[n], mod-2)) % mod;
    return 0;
}