是时候要做做数学类的题目了
这属于比较简单的矩阵快速幂了,因为有个已知的矩阵循环的结论,所以为了节约时空,只需要保留一行即可,这个稍微有点难写,也不是难写,主要是注意细节。其他的矩阵快速幂一下即可
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define N 505 #define ll long long using namespace std; struct Mat { ll mat[1][N]; }E,Z,O; ll n,m,d,k; void init() { memset(E.mat,0,sizeof E.mat); for (int i=0;i<n;i++) E.mat[i][i]=1; memset(O.mat,0,sizeof O.mat); int tmp=0; for (int j=-d;tmp<2*d+1;j++,tmp++){ if (j<0) j+=n; if (j>=n) j%=n; O.mat[0][j]=1; } // cout<<"!!!"<<endl; // for (int i=0;i<n;i++) // cout<<O.mat[0][i]<<" "; // cout<<endl; } Mat operator *(Mat a,Mat b) { Mat c=Z; int i,j; for (i=0;i<n;i++){ int cur=n-i; for (j=0;j<n;j++){ if (cur>=n) cur%=n;//因为是循环矩阵,由第一行即可推得其他列的情况 c.mat[0][i]+=a.mat[0][j]*b.mat[0][cur]; cur++; if (c.mat[0][i]>=m) c.mat[0][i]%=m; } } return c; } Mat operator ^(Mat a,ll x) { Mat c=E; for (;x;x>>=1){ if (x&1){ c=c*a; } a=a*a; } return c; } ll A[N],B[N]; int main() { memset(Z.mat,0,sizeof Z.mat); while (scanf("%lld%lld%lld%lld",&n,&m,&d,&k)!=EOF) { init(); Mat ans=O^k; // for (int i=0;i<n;i++) // cout<<ans.mat[0][i]<<" ~ "; // cout<<endl; for (int i=0;i<n;i++) scanf("%lld",&A[i]); for (int i=0;i<n;i++){ int cur=n-i; B[i]=0; for (int j=0;j<n;j++){ if (cur>=n) cur%=n; B[i]+=ans.mat[0][cur]*A[j]; cur++; if (B[i]>=m) B[i]%=m; } } printf("%lld",B[0]); for (int i=1;i<n;i++) printf(" %lld",B[i]); printf(" "); } return 0; }