逃亡 解题报告
逃亡
题意
数轴上有 \(m\) 个整型随机变量,每个单位时间内,每个随机变量会等概率增大或减小 \(1\),问 \(n\) 个单位时间内,期望有多少个整数至少被经过一次。
数据范围
设测试点编号为\(k\)
| 测试点 | \(n\) | \(m\) |
|---|---|---|
| \(1 \sim 4\) | \(\le 5000\) | \(=1\) |
| \(5 \sim 6\) | \(=\lfloor (\log_{1.04}k)^4\rfloor\) | \(=k-4\) |
| \(7 \sim 10\) | \(=\lfloor (\log_{1.04}k)^4\rfloor\) | \(=1\) |
| \(11 \sim 20\) | \(\le 100000\) | \(\le 20\) |
考场打表一时爽,放屁一点都不爽,这个题压根没拿到分数...
先考虑\(m=1,n=1e7\)的那些分
首先,题目可以被转化成求每个整数位置被经过的概率,常见的化期望为概率的方法。
然后把被经过分成两类,一类是最后停在这个点,一类是经过了这个点,这样经过每某个点可以从其他点的停在某个点的概率求过来。
先考虑一个变量从\(0\)开始停在数轴右边位置\(i\)的概率\(E(i)\),首先这个停住的位置必须和\(n\)奇偶性相同,而每一次可以走右边或左边,那么需要走右边的次数为\(\frac{n+i}{2}\),于是可以根据组合意义得到
\[E(i)=[i\equiv n\pmod 2]\frac{1}{2^n}\binom{n}{\frac{n+i}{2}}
\]
然后设\(p_i\)为经过\(i\)的概率,那么有两种情况,一种是越过了\(i\)停在\(i\)的右边,一种是停在\(i\)的左边,稍微研究一下我们可以发现,这两种情况的答案是一样的。可以这么理解,更换原点为\(i\),然后重新跑,显然两边有对称,那么\(p_i\)有
\[p_i=E_i+2\sum_{j>i}p_j
\]
推广到多个起点的情况是差不多的,仍然是求每个点的概率,相交的地方算一下不经过的概率减一下就可以了,复杂度\(O(nm^2)\)
Code:
#include <cstdio>
#include <algorithm>
const int mod=998244353;
#define add(a,b) (a+b>=mod?a+b-mod:a+b)
#define mul(a,b) (1ll*(a)*(b)%mod)
const int N=12000000;
int qp(int d,int k){int f=1;while(k){if(k&1)f=mul(f,d);d=mul(d,d),k>>=1;}return f;}
int n,m,pos[30],fac[N],inv[N],E[N],p[N];
#define C(m,n) mul(fac[m],mul(inv[n],inv[(m)-(n)]))
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d",pos+i);
fac[0]=1;for(int i=1;i<=n;i++) fac[i]=mul(fac[i-1],i);
inv[n]=qp(fac[n],mod-2);
for(int i=n-1;~i;i--) inv[i]=mul(inv[i+1],i+1);
int p2=qp(qp(2,n),mod-2);
for(int i=n&1;i<=n;i+=2) E[i]=mul(C(n,(n+i)/2),p2);
for(int i=n;i>=0;i--) p[i]=add(E[i],add(p[i+1],E[i+1]));
std::sort(pos+1,pos+1+m);
int l=pos[1]-n,r=pos[m]+n,ans=0;
for(int i=l;i<=r;i++)
{
int pn=1;
for(int j=1;j<=m;j++)
{
int d=abs(pos[j]-i);
if(d<=n) pn=mul(pn,add(1,mod-p[d]));
}
ans=add(ans,add(1,mod-pn));
}
printf("%d\n",ans);
return 0;
}
2019.1.14

浙公网安备 33010602011771号