AGC056E Cheese 题解

link

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;
}
上一篇:Codeforces 1474F - 1 2 3 4 ...(矩阵乘法)


下一篇:如何在PHP中使用正则表达式找到完全匹配的内容?