首页 > 其他分享 >C221027B

C221027B

时间:2024-08-01 16:50:24浏览次数:9  
标签:C221027B 205 matrix int cdots vdots mod

B

  • 抽 \(n\) 次卡, 连续 \(i\) 次没有抽中时, 第 \(i+1\) 次抽中的概率是 \(p_i\), 规定\(p_k=1\), 求期望抽中次数.
  • 标签:矩阵加速递推, 动态规划.
  • 暴力: 记 \(f[i][j]\) 表示已经抽了 \(i\) 次, 目前连续 \(j\) 次不中的期望抽中次数,有转移:

\[f[i][j]=f[i-1][j-1] \times (1-p[j-1]) \\ f[i][0]=\sum_{j=0}^{k}f[i-1][j] \times p[j] \]

  • 时间复杂度 \(O(NK)\).

  • 优化:矩阵加速递推

  • \[\begin{bmatrix} p_0 & p_1 & p_2 & \cdots & p_k & 0 \\ 1-p_0 & 0 & 0 & \cdots & 0 & 0 \\ 0 & 1-p_1& 0 &\cdots & 0 & 0 \\ 0 & 0 & 1-p_2&\cdots & 0 & 0 \\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots\\ 0 & 0 & \cdots & 1-p_{k-1} & 0 & 0\\ 0 & 0 & \cdots & 0 & 0 & 0 \\ p_0 & p_1 & p_2 & \cdots & p_k & 1 \\ \end{bmatrix} \times \begin{bmatrix} f_{0} \\ f_{1} \\ f_{2} \\ \vdots \\ f_{k} \\ res \\ \end{bmatrix} \]

  • 记矩阵为 \(A\)(一个 边长为 \(k+2\) 的方阵), 列向量为 \(F_0\)(其中 \(f_i=1,f_{1 \sim k}=0\))

  • 先用矩阵快速幂求出 \(A^n \times F_0\), 答案就是 \(res\)

  • 时间复杂度:本来是\(O(K^3 \times log_2^N)\), 但有一个小优化是每次 y&1=1 的时候不要另开一个单位矩阵存答案, 直接累计到那个行向量里面,这样时间复杂度会有一个 \(\frac{1}{2}\) 的常数, 会快一倍

#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=r;++i)
#define G(i,r,l) for(int i(r);i>=l;--i)
using namespace std;
using ll = long long;
const int mod=998244353;
int a[205],b[205],p[205];
int n,k;
struct matrix{
	int a[205][205];
	void init(int val=0){
		memset(a,0,sizeof(a));
		F(i,0,k+1) a[i][i]=val;
	} 
}v;
matrix operator $ (matrix A,matrix B){
	matrix C; C.init(0);
	F(i,0,k+1) F(j,0,k+1) F(z,0,k+1) C.a[i][z]=(C.a[i][z]+1ll$A.a[i][j]$B.a[j][z]%mod)%mod;
	return C;
}
void ksm(matrix A,int b){
	int f[205],g[205];
	memset(f,0,sizeof(f));
	f[0]=1;
	while(b){
		if(b&1){
			memset(g,0,sizeof(g));
			F(i,0,k+1) F(j,0,k+1) g[i]=(g[i]+1ll$A.a[i][j]$f[j])%mod;//优化在这里,单次变成K^2
			memcpy(f,g,sizeof(f));
		} 
		A=A$A;
		b>>=1;
	}
	cout<<(f[k+1]%mod+mod)%mod;
}
int quickmod(int x,int y){
	int res=1;
	while(y){
		if(y&1) res=1ll$res$x%mod;
		x=1ll$x$x%mod;
		y>>=1;
	} return res;
}
signed main(){
	freopen("card.in","r",stdin);
	freopen("card.out","w",stdout);
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin>>n>>k;
	F(i,0,k-1){
		cin>>a[i]>>b[i];
		p[i]=1ll$a[i]$quickmod(b[i],mod-2)%mod;
	} p[k]=1;
	v.init(0);
	F(i,0,k) v.a[0][i]=v.a[k+1][i]=p[i];
	F(i,1,k) v.a[i][i-1]=1-p[i-1];
	v.a[k+1][k+1]=1;
	ksm(v,n);
	return 0;
}

标签:C221027B,205,matrix,int,cdots,vdots,mod
From: https://www.cnblogs.com/superl61/p/18336989

相关文章