题面
样例输入
3 1
512962164 361666497
363881557 376525373
176039948 197582789
样例输出
510253268
277873211
210117875
512mb,2s 。
题解
由于数据全随机,所以其实在哪里出发都一样,最终出发点的影响一定会消失。每个点停留的概率会趋于稳定,而最终的稳定值,满足转移一次后概率不变。
那么,我们通过状态转移
d
p
i
?
l
i
,
j
,
d
p
i
?
r
i
,
j
??
→
?
d
p
k
dp_i*l_{i,j},dp_i*r_{i,j}~~\rightarrow~dp_k
dpi??li,j?,dpi??ri,j???→?dpk? 的矩阵可以高斯消元求出原来的
d
p
i
dp_i
dpi? 。如果仅通过这
n
n
n 个方程消元,必定会得到
n
n
n 个 0,我们需要再加一个方程
∑
d
p
i
=
1
\sum dp_i=1
∑dpi?=1 。
于是我们可以得到一个
O
(
n
3
)
O(n^3)
O(n3) 的做法,可以通过
2
k
≥
n
2k\geq n
2k≥n 的数据。
接下来我们发现,
k
k
k 非常小,因此可以带状高斯消元。但是带状高斯消元常数过大,且
n
n
n 过大时不方便存储。其实我们可以先手动消元。
我们假定前
2
k
2k
2k 个数是未知变元,可以通过这
2
k
2k
2k 个数的线性组合表示出第
2
k
+
1
2k+1
2k+1 个数,进而表示所有后面的变元。然后我们再根据这些线性组合的信息写出前
2
k
2k
2k 个数的
2
k
2k
2k 个方程加上方程
∑
d
p
i
=
1
\sum dp_i=1
∑dpi?=1 ,就可以进行高斯消元了。
需要注意的是,每一个
l
i
,
j
,
r
i
.
j
l_{i,j},r_{i.j}
li,j?,ri.j? 都必须被用上,且
n
≤
2
k
n\leq 2k
n≤2k 要特判。时间复杂度
O
(
n
k
2
)
O(nk^2)
O(nk2) ,瓶颈在于求出每个数的线性组合表示。
CODE
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<random>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 20005
#define LL long long
#define ULL unsigned long long
#define ENDL putchar('\n')
#define DB double
#define lowbit(x) (-(x) & (x))
#define FI first
#define SE second
#define eps 1e-9
int xchar() {
static const int maxn = 1000000;
static char b[maxn];
static int pos = 0,len = 0;
if(pos == len) pos = 0,len = fread(b,1,maxn,stdin);
if(pos == len) return -1;
return b[pos ++];
}
LL read() {
LL f = 1,x = 0;int s = getchar();
while(s < '0' || s > '9') {if(s<0)return -1;if(s=='-')f=-f;s = getchar();}
while(s >= '0' && s <= '9') {x = (x<<1) + (x<<3) + (s^48);s = getchar();}
return f*x;
}
void putpos(LL x) {if(!x)return ;putpos(x/10);putchar((x%10)^48);}
void putnum(LL x) {
if(!x) {putchar('0');return ;}
if(x<0) putchar('-'),x = -x;
return putpos(x);
}
void AIput(LL x,int c) {putnum(x);putchar(c);}
const int MOD = 998244353;
int n,m,s,o,k;
int qkpow(int a,int b) {
int res = 1;
while(b>0) {
if(b & 1) res = res *1ll* a % MOD;
a = a *1ll* a % MOD; b >>= 1;
}return res;
}
int l[MAXN][55],r[MAXN][55];
int b[105],kk[MAXN][105];
int a[305][305];
void Gauss(int n) {
for(int i = 0;i < n;i ++) {
for(int j = i+1;j <= n;j ++) {
if(a[j][i]) {swap(a[i],a[j]);break;}
}
int iv = qkpow(a[i][i],MOD-2);
for(int j = i;j <= n;j ++) a[i][j] = a[i][j] *1ll* iv % MOD;
for(int j = 0;j <= n;j ++) {
if(j == i || !a[j][i]) continue;
for(int k = n;k >= i;k --) {
(a[j][k] += MOD-a[i][k]*1ll*a[j][i]%MOD) %= MOD;
}
}
}return ;
}
int main() {
n = read(); m = read();
for(int i = 0;i < n;i ++) {
int su = 0;
for(int j = m;j > 0;j --) {
l[i][j] = read();
(su += l[i][j]) %= MOD;
}
for(int j = 1;j <= m;j ++) {
r[i][j] = read();
(su += r[i][j]) %= MOD;
}
l[i][0] = MOD-1;
su = qkpow(su,MOD-2);
for(int j = 1;j <= m;j ++) {
l[i][j] = l[i][j] *1ll* su % MOD;
r[i][j] = r[i][j] *1ll* su % MOD;
}
}
if(2*m >= n) {
for(int i = 0;i < n;i ++) {
(a[i][i] += MOD-1) %= MOD;
for(int j = 1;j <= m;j ++) {
(a[(i+n-j)%n][i] += l[i][j]) %= MOD;
(a[(i+j)%n][i] += r[i][j]) %= MOD;
}
}
for(int i = 0;i <= n;i ++) a[n][i] = 1;
Gauss(n);
for(int i = 0;i < n;i ++) AIput(a[i][n],'\n');
return 0;
}
for(int i = 0;i < m;i ++) b[i] = i,kk[i][i] = 1;
for(int i = n-m;i < n;i ++) b[m+n-i-1] = i,kk[i][m+n-i-1] = 1;
for(int i = m;i < n-m;i ++) {
int iv = qkpow(l[i][m],MOD-2),p = i-m;
for(int j = 0;j < m;j ++) {
int y = (p+j)%n;
int xs = l[y][j]*1ll*iv%MOD;
for(int k = 0;k < 2*m;k ++) {
kk[i][k] = (kk[y][k]*1ll*xs + kk[i][k]) % MOD;
}
}
for(int j = 1;j <= m;j ++) {
int y = (p+n-j)%n;
int xs = r[y][j]*1ll*iv%MOD;
for(int k = 0;k < 2*m;k ++) {
kk[i][k] = (kk[y][k]*1ll*xs + kk[i][k]) % MOD;
}
}
for(int j = 0;j < 2*m;j ++) kk[i][j] = (MOD-kk[i][j]) % MOD;
}
for(int i = 0;i < 2*m;i ++) {
int x = b[i];
int iv = qkpow(l[x][m],MOD-2),p = (x+n-m)%n;
a[i][i] = 1;
for(int j = 0;j < m;j ++) {
int y = (p+j)%n;
int xs = l[y][j]*1ll*iv%MOD;
for(int k = 0;k < 2*m;k ++) {
a[i][k] = (kk[y][k]*1ll*xs + a[i][k]) % MOD;
}
}
for(int j = 1;j <= m;j ++) {
int y = (p+n-j)%n;
int xs = r[y][j]*1ll*iv%MOD;
for(int k = 0;k < 2*m;k ++) {
a[i][k] = (kk[y][k]*1ll*xs + a[i][k]) % MOD;
}
}
}
for(int i = 0;i < n;i ++) {
for(int j = 0;j < 2*m;j ++) {
a[m<<1][j] = (kk[i][j] + a[m<<1][j]) % MOD;
}
}
a[m<<1][m<<1] = 1;
Gauss(m<<1);
for(int i = 0;i < n;i ++) {
int as = 0;
for(int j = 0;j < 2*m;j ++) {
(as += a[j][m<<1]*1ll*kk[i][j]%MOD) %= MOD;
}
AIput(as,'\n');
}
return 0;
}
|