UVA - 1386 Cellular Automaton (矩阵快速幂)

来源:互联网 发布:淘宝旺铺2016年多少钱 编辑:程序博客网 时间:2024/05/21 08:48

Cellular Automaton
Time Limit: 18000MS  64bit IO Format: %lld & %llu

Submit Status uDebug

Description

Download as PDF

题意:

对一个圈里的n个数字进行操作,每次操作都将数字i与其相邻距离d以内的数字加起来对m取余。共进行k次操作,问你k次操作后各数为多少。

分析:

感觉上是矩阵快速幂,没想到n这么大,书上写的循环矩阵悟了半天也悟不到,最后貌似由于矩阵开太大,传参时爆内存。最后发现了循环矩阵的做法是只求第一行,但是处理矩阵相乘时需要注意,因为循环矩阵可由第一行求出整个矩阵,因此顺序需要搞清楚。相乘搞定了其他都是基本的快速幂过程。

#include <algorithm>#include <iostream>#include <sstream>#include <cstring>#include <cstdlib>#include <string>#include <vector>#include <cstdio>#include <cmath>#include <queue>#include <stack>#include <map>#include <set>using namespace std;#define INF 0x3f3f3f3fconst long long N=505;const long long mod=1e9;const double PI=acos(-1.0);typedef long long ll;typedef struct {    ll mat[N];}Mat;int n,d,m,k;Mat multi(Mat a,Mat b) {    Mat c;    memset(c.mat, 0, sizeof(c.mat));    for (int i=1; i<=n; i++) {        for (int j=1; j<=n; j++) {            c.mat[i]+=a.mat[j]*b.mat[(i-j+n)%n+1];            c.mat[i]%=m;        }    }    return c;}Mat qui(Mat a,int b) {    Mat c;    memset(c.mat, 0, sizeof(c.mat));            c.mat[1]=1;    while (b) {        if (b&1) {            c=multi(c, a);        }        a=multi(a, a);        b>>=1;    }    return c;}int main() {    int f[N];    Mat A;    while (cin>>n>>m>>d>>k) {        memset(f, 0, sizeof(f));        for (int i=1; i<=n; i++) {            scanf("%d",&f[i]);        }        memset(A.mat, 0, sizeof(A.mat));                for (int i=1; i<=1; i++) {            A.mat[i]=1;            for (int j=1; j<=d; j++) {                A.mat[(i-1+j)%n+1]=1;                A.mat[(i-1-j+n)%n+1]=1;            }        }        A=qui(A, k);        ll res[N];        memset(res, 0, sizeof(res));        for (int i=1; i<=n; i++) {            for (int j=1; j<=n; j++) {                //                cout<<A.mat[(j+i-2)%n+1]*f[j]<<endl;                res[i]+=A.mat[(i-j+n)%n+1]*f[j];                res[i]%=m;            }        }        for (int i=1; i<n; i++) {            printf("%lld ",res[i]);        }        cout<<res[n]<<endl;    }    return 0;}



0 0