Date:2022.01.15
题意:有n+2n+2n+2个塔编号从[0,n+1][0,n+1][0,n+1],在每个塔上建一个通讯器的概率都是12\frac{1}{2}21,设每个通讯器传送半径为ppp,所在下标为iii,即能传送讯息给[i−(p−1),i+(p−1)][i-(p-1),i+(p-1)][i−(p−1),i+(p−1)]中的所有元素。要求:
①不能给下标为000和n+1n+1n+1的塔传送消息。
②给下标为[1,n][1,n][1,n]的所有塔都能收到消息,且只收到111次。
求方案数。

思路:设f[i]f[i]f[i]:不包含塔0、n+10、n+10、n+1,且长度为iii的方案数。求当前f[i]f[i]f[i]时分别让1...⌈n2⌉1...\lceil\frac{n}{2}\rceil1...⌈2n⌉处的ppp满足向左取到111,只有这样右边才不会取到n+1n+1n+1,再依次累加每一类的方案数。
①f[1]:1f[1]:1f[1]:1,i=1,只有这1种方案,贡献1。i=1,只有这1种方案,贡献1。i=1,只有这1种方案,贡献1。
②f[2]:f[1]f[2]:f[1]f[2]:f[1]。i=1,占[1,1],其右边相当于f[1]种方案i=1,占[1,1],其右边相当于f[1]种方案i=1,占[1,1],其右边相当于f[1]种方案。
③f[3]:f[2]+1f[3]:f[2]+1f[3]:f[2]+1。i=1,占[1,1],其右边相当于f[2]种方案;i=2,占[1,3],仅1种可能i=1,占[1,1],其右边相当于f[2]种方案;i=2,占[1,3],仅1种可能i=1,占[1,1],其右边相当于f[2]种方案;i=2,占[1,3],仅1种可能。
④f[4]:f[3]+f[1]f[4]:f[3]+f[1]f[4]:f[3]+f[1]。i=1,占[1,1],其右边相当于f[3]种方案;i=2,占[1,3],其右边相当于f[1]种方案i=1,占[1,1],其右边相当于f[3]种方案;i=2,占[1,3],其右边相当于f[1]种方案i=1,占[1,1],其右边相当于f[3]种方案;i=2,占[1,3],其右边相当于f[1]种方案。
⑤f[5]:f[4]+f[2]+1f[5]:f[4]+f[2]+1f[5]:f[4]+f[2]+1。i=1,占[1,1],其右边相当于f[4]种方案;i=2,占[1,3],其右边相当于f[2]种方案;i=3,占[1,5],只有这1种方案。i=1,占[1,1],其右边相当于f[4]种方案;i=2,占[1,3],其右边相当于f[2]种方案;i=3,占[1,5],只有这1种方案。i=1,占[1,1],其右边相当于f[4]种方案;i=2,占[1,3],其右边相当于f[2]种方案;i=3,占[1,5],只有这1种方案。
…
因此可归纳得到:
f[i]=∑k=0⌊i−12⌋f[i−2⋅k−1]f[i]=\sum_{k=0}^{\lfloor\frac{i-1}{2}\rfloor}f[i-2·k-1]f[i]=∑k=0⌊2i−1⌋f[i−2⋅k−1]
将iii分奇偶,再次将右边所有项归纳,不难得出:
f[i]=f[i−1]+f[i−2]f[i]=f[i-1]+f[i-2]f[i]=f[i−1]+f[i−2]
由此便求出所有f[i]f[i]f[i]。
因此答案即为:
f[n]∗12n%998244353f[n] * \frac{1}{2^n} \% 998244353f[n]∗2n1%998244353
即一个斐波那契数列,但由于每种方案的概率都是12n\frac{1}{2^n}2n1,因此要除12n\frac{1}{2^n}2n1。除法取模涉及同余,因此要找2n2^n2n在mod998244353mod 998244353mod998244353意义下的逆元。又因为998244353998244353998244353为质数,因此(2n,998244353)==1(2^n,998244353)==1(2n,998244353)==1,费马小定理+快速幂求解。
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 2e5+10,mod=998244353;
typedef long long LL;
LL a[N],f[N];
LL qmi(LL a,LL k,LL p)
{
LL res=1;
while(k)
{
if(k&1) res=res*a%mod;
a=a*a%mod;
k>>=1;
}
return res;
}
int main()
{
LL n;cin>>n;
f[1]=f[2]=1;
for(int i=3;i<=n;i++)
f[i]=(f[i-1]+f[i-2])%mod;
cout<<f[n]*qmi(qmi(2,n,mod),mod-2,mod)%mod<<' ';
return 0;
}

本文探讨了一个关于在一系列编号的塔上建立通讯器的问题。目标是确保特定范围内的塔能够恰好接收一次消息,并给出了求解该问题的有效算法及其实现代码。

被折叠的 条评论
为什么被折叠?



