LA 3704 Cellular Automaton(循环矩阵)

来源:互联网 发布:信长之野望 知乎 编辑:程序博客网 时间:2024/05/08 00:50

题目链接

分析:这题矩阵规模略大,直接算下来要500^3*log(10^7),不过有个非常好的性质可以利用,循环矩阵*循环矩阵 = 循环矩阵 ,这样就可以将复杂度降低500;

参考代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 550;typedef long long LL;typedef LL Mat[maxn];int N,M,D,K,tot;Mat m[100];int E[maxn];LL ans[maxn];int Mul(int a,int b){    int r = ++tot;    for(int i=0;i<N;i++){        LL sum = 0;        for(int j=0;j<N;j++){            sum += m[a][j]*m[b][(i-j+N)%N];        }        m[r][i] = sum % M;    }    return r;}int Pow(int n){    int e = 0,a=1;    while(n){        if(n&1) e = Mul(e,a);        a = Mul(a,a);        n>>=1;    }    return e;}int main(){    //freopen("input.txt","r",stdin);    while(scanf("%d%d%d%d",&N,&M,&D,&K)!=EOF){        tot = 1;        for(int i=0;i<N;i++) scanf("%d",&E[i]);        for(int i=0;i<N;i++){            m[0][i] = i==0 ? 1 : 0;            m[1][i] = (i<=D || N-i<=D) ? 1 : 0;        }        int r = Pow(K);        for(int i=0;i<N;i++){            ans[i] = 0;            for(int j=0;j<N;j++){                ans[i] = (ans[i] + m[r][(j-i+N)%N] * E[j]) % M;            }        }        printf("%lld",ans[0]);        for(int i=1;i<N;i++) printf(" %lld",ans[i]);        printf("\n");    }    return 0;}


原创粉丝点击