Cellular Automaton UVA - 1386
无数次次RE原因竟然是,开了一个int的n输入用ll型的,简直分分钟奔溃。
思路:开n*n的矩阵内存会爆,这里通过找系数矩阵的规律,用一行代表n行的数。
例如样例1的第一行系数矩阵:1 1 0 0 1,第二行时右移一位1 1 1 0 0 后面即使变换后也是这个道理。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
typedef long long ll;
struct matrix{
ll x[551];
};
ll n,m;
matrix multi(matrix a,matrix b){
matrix temp;
memset(temp.x,0,sizeof(temp.x));
int t=0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(t==n) t=0;
temp.x[i]+=a.x[j]*b.x[t++];
}
t--;temp.x[i]%=m;
}
return temp;
}
matrix quick_multi(matrix a,ll k)//矩阵快速幂
{
if(k==1) return a;
matrix temp;
memset(temp.x,0,sizeof(temp.x));
temp.x[0]=1;
if(k==0) return temp;
while(k){
if(k&1)
temp=multi(temp,a);
a=multi(a,a);
k>>=1;
}
return temp;
}
int main()
{
int d,k;
ll b[550];matrix a;
while(scanf("%lld%lld%lld%lld",&n,&m,&d,&k)!=EOF)
{
memset(a.x,0,sizeof(a.x));
memset(b,0,sizeof(b));
for(int i=0;i<n;i++) scanf("%lld",&b[i]);
a.x[0]=1;
for(int i=1;i<=d;i++)
{
a.x[i]=1;
int p=-i;if(p<0) p+=n;
a.x[p]=1;
}
a=quick_multi(a,k);
//for(int i=0;i<n;i++) cout<<a.x[i]<<" ";
//cout<<endl;
int t=0;
for(int i=0;i<n;i++){
ll ans=0;
for(int j=0;j<n;j++){
if(t==n) t=0;
ans+=b[j]*a.x[t++];
}
t--;ans%=m;//少取余??
i==0?printf("%lld",ans):printf(" %lld",ans);
}
printf("\n");
}
return 0;
}