AGC056E Cheese 题解
Solution
我们可以发现的是,奶酪的投放顺序不会影响我们老鼠能否吃到的概率。考虑破环成链(编号 \(0\) ~ \(n-1\)),然后我们可以设 \(c_i\) 表示第 \(i\) 段的奶酪个数,\(x\) 为越过整圈的次数,那么对于第 \(n-1\) 只老鼠,它吃不到的概率就是:
\[2^{-x}\prod_{i=0}^{n-2} (1-2^{-(x-i+\sum_{j=0}^{i} c_j)})
\]
然后你发现我们可以求出关于 \(2^{-x}\) 的多项式,然后对于每一项就可以带入式子,统一计算 \(\sum_{x} 2^{-x}\)。
复杂度 \(\Theta(n^5)\) ,据说有时间复杂度更优秀的做法,但是我太屑了,并不会。
Code
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define mod 998244353
#define MAXN 45
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}
int n,A[MAXN],fac[MAXN],fuc[MAXN],val[MAXN],ifac[MAXN],f[MAXN][MAXN],g[MAXN][MAXN];
int mul (int a,int b){return 1ll * a * b % mod;}
int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
int qkpow (int a,int b){
if (b < 0) b += mod - 1;
int res = 1;for (;b;b >>= 1,a = mul (a,a)) if (b & 1) res = mul (res,a);
return res;
}
void Add (int &a,int b){a = add (a,b);}
void Sub (int &a,int b){a = dec (a,b);}
void solve (){
memset (f,0,sizeof (f)),f[0][0] = fuc[0] = 1;
for (Int i = 0;i < n;++ i){
for (Int j = 1;j < n;++ j) fuc[j] = mul (fuc[j - 1],val[i]);
for (Int j = 0;j < n;++ j) fuc[j] = mul (fuc[j],ifac[j]);
memset (g,0,sizeof (g));
for (Int j = 0;j < n;++ j)
for (Int k = 0;j + k < n;++ k)
for (Int l = 0;l <= i;++ l) Add (g[j + k][l],mul (f[j][l],fuc[k]));
memset (f,0,sizeof (f));
for (Int j = 0;j < n;++ j){
int v = qkpow (2,i - j);
if (i == n - 1) for (Int k = 0;k < n;++ k) Add (f[j][k + 1],mul (v,g[j][k]));
else for (Int k = 0;k <= i;++ k) Add (f[j][k],g[j][k]),Sub (f[j][k + 1],mul (v,g[j][k]));
}
}
int res = 0;
for (Int i = 1,pw = 1;i <= n;++ i) Add (res,mul (f[n - 1][i],mul (pw,qkpow (2 * pw - 1,mod - 2)))),pw = add (pw,pw);
write (mul (res,fac[n - 1])),putchar (' ');
}
signed main(){
read (n),fac[0] = 1;int iv100 = qkpow (100,mod - 2);
for (Int i = 1;i <= n;++ i) fac[i] = mul (fac[i - 1],i);
ifac[n] = qkpow (fac[n],mod - 2);for (Int i = n;i;-- i) ifac[i - 1] = mul (ifac[i],i);
for (Int i = 0;i < n;++ i) read (A[i]),A[i] = mul (A[i],iv100);
for (Int i = 0;i < n;++ i){
for (Int j = 0;j <= i;++ j) val[n + j - i - 1] = A[j];
for (Int j = i + 1;j < n;++ j) val[j - i - 1] = A[j];
solve ();
}
putchar ('\n');
return 0;
}