D
题解
初始人数分布可以看作初始状态,有一定概率转移到别的位置,视为状态转移,因此矩阵快速幂可以解决。但是直接使用矩阵快速幂的时间复杂度为,超时。需要改进矩阵乘法,观察到状态转移矩阵是一个循环矩阵,循环矩阵与循环矩阵相乘仍然为循环矩阵,因此,只需要保存矩阵的第一行,两个矩阵相乘时,通过两个矩阵第一行的元素,可以求得结果矩阵的第一行元素,即结果矩阵可得。时间复杂度
.
代码
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 0x3f3f3f3f const ll mod=998244353; ll n,k; ll a,b,c,s; vector<ll> trans,state0; ll pow_mod(ll a, ll x, ll p) { ll ret = 1; while (x) { if (x & 1) ret = ret * a % p; a = a * a % p; x >>= 1; } return ret; } vector<ll> mul(vector<ll> &a,vector<ll> &b) { vector<ll> res(n); for(int i=0;i<n;++i) { ll now=0; for(int j=0;j<n;++j) now=(now+a[(i+n-j)%n]*b[j]%mod)%mod; res[i]=now; } return res; } int main(void) { cin>>n>>k>>a>>b>>c; s=a+b+c; ll inverses=pow_mod(s,mod-2,mod); ll p1=a*inverses%mod; ll p2=b*inverses%mod; ll p3=c*inverses%mod; state0.resize(n); trans.resize(n,0); for(int i=0;i<n;++i) cin>>state0[i]; trans[0]=p3,trans[1]=p1,trans[n-1]=p2; vector<ll> tmp(n,0); tmp[0]=1; while(k) { if(1&k) tmp=mul(tmp,trans); trans=mul(trans,trans); k>>=1; } vector<ll> ans=mul(state0,tmp); for(auto x:ans) cout<<x<<" "; cout<<endl; return 0; }