利用循环矩阵相乘仍是循环矩阵的性质,将复杂度从n^3*log(k)降到n^2*log(k)。
而且a[500][500]做传参太大, 程序会直接崩掉。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
typedef long long LL;
typedef unsigned long long LLU;
using namespace std;
const int N=500+1;
int MOD, n, k, d;
LL res[N], init[N];
void Mult(LL a[], LL b[])
{
LL c[N];
for(int i=0; i<n; i++)
{
c[i]=0;
for(int j=0; j<n; j++)
c[i]=(c[i]+a[j]*b[(i-j+n)%n])%MOD;
}
memcpy(a, c, sizeof(c));
}
void Pow(int b)
{
memset(res, 0, sizeof(res));
memset(init, 0, sizeof(init));
for(int i=0; i<=d; i++)
init[i]=init[(n-i)%n]=1;
res[0]=1;
while(b)
{
if(b&1)Mult(res, init);
Mult(init, init);
b>>=1;
}
}
int main()
{
while(~scanf("%d%d%d%d", &n, &MOD, &d, &k))
{
Pow(k);
LL a[N], ans[N]={0};
for(int i=0; i<n; i++)
scanf("%d", &a[i]);
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
ans[i]=(ans[i]+a[j]*res[(i+n-j)%n])%MOD;
printf("%lld", ans[0]);
for(int i=1; i<n; i++)
printf(" %lld", ans[i]);
printf("\n");
}
return 0;
}