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;
}