前言
奶酪可能会长腿,但绝对不会变质
_ _,_ _ _ _ _ _ _
正题
题目链接:https://atcoder.jp/contests/agc056/tasks/agc056_e
题目大意
有一个长度为nnn的环,第i+0.5(0≤i<n)i+0.5(0\leq i<n)i+0.5(0≤i<n)位置上各有一只老鼠。
然后进行以下操作n−1n-1n−1次:
第iii个位置有ai%a_i\%ai%的概率被选择(选择一个),然后在这个位置上放一个奶酪,这个奶酪会顺时针跑,跑到一个老鼠的位置时有50%50\%50%的概率被吃掉,老鼠如果吃过奶酪就会离开。
求每只老鼠被留到最后的概率。
1≤n≤50,∑i=0n−1ai=1001\leq n\leq 50,\sum_{i=0}^{n-1}a_i=1001≤n≤50,∑i=0n−1ai=100
解题思路
考虑第nnn只老鼠留到最后的概率,因为无论是哪只奶酪吃什么老鼠都是一样的,所以我们可以考虑开始时就将所有的奶酪放下来,然后让它们一起绕着环走。
同样的,奶酪的移动顺序也是无关紧要的,所以我们可以考虑让所有的奶酪先绕道第nnn只老鼠的面前然后一起统计。
那么先考虑dpdpdp,设fi,j,kf_{i,j,k}fi,j,k表示现在已经放下的奶酪都已经走到了位置iii处,然后已经放下了jjj个奶酪,已经有kkk个被老鼠吃了。
那么每次的转移分成两部分,第一部分是放奶酪,枚举这个位置放置了xxx个奶酪,需要注意的是除了概率以外因为这个方案是涉及可重排列的,所以还需要乘上一个1x!\frac{1}{x!}x!1。
第二部分是吃奶酪,因为每只奶酪只会吃一个老鼠,所以统计没有这些奶酪都没有被吃的概率,很方便转移。
那么假设目前有kkk个奶酪走到了第nnn只老鼠前,那么说明前面还剩下k−1k-1k−1只老鼠没有被吃,那么考虑这种情况下第nnn只老鼠被留到最后的概率。
考虑一个神必的证明方法,我们考虑绕一圈绕到第iii只老鼠处还剩下xxx个奶酪,然后考虑iii和i+1i+1i+1之间被留到最后的概率:
- 如果iii和i+1i+1i+1都吃到了,我们显然得不出两个的概率关系。
- 如果iii和i+1i+1i+1都没被吃到,我们也得不出来,考虑下一轮。
- 如果iii吃了并且i+1i+1i+1没吃,概率是(1−12x)12x−1(1-\frac{1}{2^x})\frac{1}{2^{x-1}}(1−2x1)2x−11
- 如果iii没吃并且i+1i+1i+1吃了,概率是12x(1−12x)\frac{1}{2^x}(1-\frac{1}{2^x})2x1(1−2x1)
那么记pip_ipi表示iii留到最后的概率,就有pi:pi+1=12x(1−12x):(1−12x)12x−1=1:2p_i:p_{i+1}=\frac{1}{2^x}(1-\frac{1}{2^x}):(1-\frac{1}{2^x})\frac{1}{2^{x-1}}=1:2pi:pi+1=2x1(1−2x1):(1−2x1)2x−11=1:2
然后又因为∑i=1k−1pi=1\sum_{i=1}^{k-1}p_i=1∑i=1k−1pi=1,所以有pi=2i−12k−1p_i=\frac{2^{i-1}}{2^{k}-1}pi=2k−12i−1,那么我们要求的就是p1=12k−1p_1=\frac{1}{2^k-1}p1=2k−11
然后这样是求第nnn只老鼠的,改一下其他的aia_iai就好了。
时间复杂度:O(n5)O(n^5)O(n5)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=55,P=998244353;
ll n,fac[N],inv[N],pw[N],pr[N];
ll a[N],f[N][N][N];
ll power(ll x,ll b){ll ans=1;while(b){if(b&1)ans=ans*x%P;x=x*x%P;b>>=1;}return ans;
}
signed main()
{scanf("%lld",&n);fac[0]=inv[0]=inv[1]=pw[0]=pr[0]=1;for(ll i=2;i<N;i++)inv[i]=P-inv[P%i]*(P/i)%P;for(ll i=1;i<N;i++)fac[i]=fac[i-1]*i%P,inv[i]=inv[i-1]*inv[i]%P;for(ll i=1;i<N;i++)pw[i]=pw[i-1]*inv[2]%P,pr[i]=pr[i-1]*2ll%P;for(ll i=0;i<n;i++)scanf("%lld",&a[i]),a[i]=a[i]*power(100,P-2)%P;ll sum=0;for(ll s=0;s<n;s++){//f[i][j][k]表示到s+i,j个奶酪,被吃了k个memset(f,0,sizeof(f));f[0][0][0]=1;for(ll x=1;x<=n;x++){for(ll i=0;i<n;i++)for(ll j=0;j<=i;j++)for(ll k=0,r=1;k<=i-j;k++,r=r*a[(s+x)%n]%P)(f[x][i][j]+=f[x-1][i-k][j]*r%P*inv[k]%P)%=P;if(x==n)continue;for(ll i=0;i<n;i++)for(ll j=i-1;j>=0;j--){(f[x][i][j+1]+=f[x][i][j]*(1-pw[i-j])%P)%=P;(f[x][i][j]=f[x][i][j]*pw[i-j]%P)%=P;}}ll ans=0;for(ll i=1;i<=n;i++)(ans+=f[n][n-1][n-i]*fac[n-1]%P*power(pr[i]-1,P-2)%P)%=P;printf("%lld ",(ans+P)%P);sum=(sum+ans)%P;}return 0;
}