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;
}
京公网安备 11010502036488号