\(\text{Solution}\)

容易发现其实就是将长度为 \(n\) 的区间划分成若干奇数段的总方案数再除以 \(2^n\)

解释一下就是因为每个小镇选与不选的概率都是 \(\frac{1}{2}\),那么每种方案的概率都是一样的。

我们发现 \(0,n+1\) 不能收到信号其实就是将 \([1,n]\) 阻断起来,很容易联想到 \(\text{DP}\) 的子状态:\(f[i]\) 表示 \(i\) 个小镇的总方案数,那我们就有转移柿(枚举最后一段长度为 \(2\times j+1\)\(f[0]=0\)):

  • \(i\) 为偶数:

\[f[i]=\sum_{j=0}^{\frac{i-1}{2}} f[i-2\times j-1] \]

  • \(i\) 为奇数(加 \(1\) 是因为本身可以成为一种长度为 \(i\) 方案):

\[f[i]=1+\sum_{j=0}^{\frac{i-1}{2}} f[i-2\times j-1] \]

这个时候就可以分奇偶做前缀和优化以 \(\mathcal O(n)\) 的优秀复杂度通过此题。

但其实这个柿子暗藏玄机,其实 \(f[n]\) 就是 \(\text{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\)

\(\text{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,'\n');
	return 0;
}
posted on 2020-12-03 23:13  Oxide  阅读(148)  评论(0编辑  收藏  举报