( ext{Solution})
容易发现其实就是将长度为 (n) 的区间划分成若干奇数段的总方案数再除以 (2^n)。
解释一下就是因为每个小镇选与不选的概率都是 (frac{1}{2}),那么每种方案的概率都是一样的。
我们发现 (0,n+1) 不能收到信号其实就是将 ([1,n]) 阻断起来,很容易联想到 ( ext{DP}) 的子状态:(f[i]) 表示 (i) 个小镇的总方案数,那我们就有转移柿(枚举最后一段长度为 (2 imes j+1),(f[0]=0)):
- 若 (i) 为偶数:
[f[i]=sum_{j=0}^{frac{i-1}{2}} f[i-2 imes j-1]
]
- 若 (i) 为奇数(加 (1) 是因为本身可以成为一种长度为 (i) 方案):
[f[i]=1+sum_{j=0}^{frac{i-1}{2}} f[i-2 imes j-1]
]
这个时候就可以分奇偶做前缀和优化以 (mathcal O(n)) 的优秀复杂度通过此题。
但其实这个柿子暗藏玄机,其实 (f[n]) 就是 ( ext{Fib}[n])!(针对数据思考)
首先 (f[1],f[2]) 肯定满足。
还是分奇偶讨论:
- 若 (n) 为偶数:
[f[n]=f[1]+f[3]+f[5]+...+f[n-1]
]
[=f[2]+f[3]+f[5]+...+f[n-1]
]
[=f[4]+f[5]+...+f[n-1]
]
[=f[n-2]+f[n-1]
]
- 若 (n) 为奇数:
[f[n]=1+f[2]+f[4]+...+f[n-1]
]
[=f[1]+f[2]+f[4]+...+f[n-1]
]
[=f[3]+f[4]+...+f[n-1]
]
[=f[n-2]+f[n-1]
]
从 (3) 开始我们这样递推地证明,可以一直推到 (n)。
( ext{Code})
#include <cstdio>
#define rep(i,_l,_r) for(signed i=(_l),_end=(_r);i<=_end;++i)
#define print(x,y) write(x),putchar(y)
template <class T> inline T read(const T sample) {
T x=0; int f=1; char s;
while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
return x*f;
}
template <class T> inline void write(T x) {
if(x<0) return (void)(putchar('-'),write(-x));
if(x>9) write(x/10);
putchar(x%10^48);
}
#include <iostream>
using namespace std;
const int mod=998244353;
int n,a=1,b=1;
int qkpow(int x,int y) {
int r=1;
while(y) {
if(y&1) r=1ll*r*x%mod;
x=1ll*x*x%mod; y>>=1;
}
return r;
}
int main() {
n=read(9);
rep(i,3,n) a=(a+b)%mod,swap(a,b);
print(1ll*b*qkpow(qkpow(2,n),mod-2)%mod,'
');
return 0;
}