Uva 1386 - Cellular Automaton ( 矩阵乘法 + 循环矩阵 )

Uva 1386 - Cellular Automaton ( 矩阵乘法 + 循环矩阵 )

#include <cstdio>
#include <cstring>
#define CLR( a, b ) memset( a, b, sizeof(a) )
int MOD;
#define MAX_SIZE 500

struct Mat
{
    int n;
    LL mat[MAX_SIZE][MAX_SIZE];

    Mat( int _n = 0 )
    {
        n = _n;
        CLR( mat, 0 );
    }
    void init()
    {
        for( int i = 0; i < n; ++i )
            for( int j = 0; j < n; ++j )
                mat[i][j] = ( i == j );
    }
    Mat operator + ( const Mat &b ) const
    {
        Mat t( n );
        for( int i = 0; i < n; ++i )
            for( int j = 0; j < n; ++j )
                t.mat[i][j] = ( mat[i][j] + b.mat[i][j] ) % MOD;
        return t;
    }
    Mat operator * ( const Mat &b ) const
    {
        Mat t( n );
        for( int k = 0; k < n; ++k )
            for( int i = 0; i < n; ++i ) if( mat[i][k] )
                for( int j = 0; j < n; ++j )
                    t.mat[i][j] = ( t.mat[i][j] + mat[i][k] * b.mat[k][j] ) % MOD;
        return t;

    }
    void debug()
    {
        for( int i = 0; i < n; ++i )
        {
            for( int j = 0; j < n; ++j )
            {
                if( j !=0 )    putchar( ‘ ‘ );
                printf( "%d", mat[i][j] );
            }
            putchar( ‘\n‘ );
        }
    }
};

Mat fast_mod( Mat a, int b )
{
    Mat c( a.n );
    c.init();
    while( b )
    {
        if( b & 1 ) c = c * a;
        a = a * a;
        b >>= 1;
    }
    return c;
}

void scan( int &x )
{
    char c;
    while( c = getchar(), c < ‘0‘ || c > ‘9‘ );
    x = c - ‘0‘;
    while( c = getchar(), c >= ‘0‘ && c <= ‘9‘ )    x = x * 10 + c - ‘0‘;
}

void Orz()
{
    int n, d, k;
    while( ~scanf( "%d %d %d %d", &n, &MOD, &d, &k ) )
    {
        Mat c( n );
        for( int i = 0; i < n; ++i )
            scan( c.mat[i][0] );
        Mat t( n );
        for( int i = 0; i < n; ++i )
        {
            t.mat[i][i] = 1;
            for( int j = 1; j <= d; ++j )
            {
                int t1 = i - j;
                int t2 = i + j;
                if( t1 < 0 ) t1 += n;
                t.mat[i][t1] = 1;
                if( t2 > n-1 )  t2 -= n;
                t.mat[i][t2] = 1;
            }
        }
        //t.debug();
        t = fast_mod( t, k );
        t = t * c;
        for( int i = 0; i < n; ++i )
        {
            if( i != 0 )    putchar( ‘ ‘ );
            printf( "%d", t.mat[i][0] );
        }
        putchar( ‘\n‘ );
    }
}

int main()
{
    Orz();
    return 0;
}

开始写的错误代码

#include <cstdio>
#include <cstring>
#define CLR( a, b ) memset( a, b, sizeof(a) )
#define MAXN 500
typedef long long LL;
int n, d, k, MOD;
LL A[MAXN], B[MAXN];

void mul( LL *a, LL *b )
{
    LL c[MAXN] = {0};
    for( int i = 0; i < n; ++i )
        for( int j = 0; j < n; ++j )
            c[i] += a[j] * b[ i <= j ? ( j - i ) : ( n - i + j ) ];
    for( int i = 0; i < n; ++i )
        a[i] = c[i] % MOD;
}

void fast_mod( int b )
{
    while( b )
    {
        if( b & 1 ) mul( A, B );
        mul( B, B );
        b >>= 1;
    }
}

void scan( LL &x )
{
    char c;
    while( c = getchar(), c < ‘0‘ || c > ‘9‘ );
    x = c - ‘0‘;
    while( c = getchar(), c >= ‘0‘ && c <= ‘9‘ )    x = x * 10 + c - ‘0‘;
}

int main()
{
    while( ~scanf( "%d %d %d %d",&n, &MOD, &d, &k ) )
    {
        CLR( A, 0 ); CLR( B, 0 );
        for( int i = 0; i < n; ++i )
            scan( A[i] );
        for( int i = -d; i <= d; ++i )
            B[( i + n ) % n ] = 1;
        fast_mod( k );
        for( int i = 0; i < n; ++i )
        {
            if( i != 0 ) putchar( ‘ ‘ );
            printf( "%lld", A[i] );
        } 

        putchar( ‘\n‘ );
    }
}

AC代码君-细节的东西自己注意吧

时间: 2024-10-25 20:53:33

Uva 1386 - Cellular Automaton ( 矩阵乘法 + 循环矩阵 )的相关文章

UVA 1386 - Cellular Automaton(循环矩阵)

UVA 1386 - Cellular Automaton 题目链接 题意:给定一个n格的环,现在有个距离d,每次变化把环和他周围距离d以内的格子相加,结果mod m,问经过k次变换之后,环上的各个数字 思路:矩阵很好想,每个位置对应周围几个位置为1,其余位置为0,但是这个矩阵有500,有点大,直接n^3去求矩阵不太合适,然后观察发现这个矩阵是个循环矩阵,循环矩阵相乘的话,只需要保存一行即可,然后用n^2的时间就足够计算了 代码: #include <stdio.h> #include <

UVA - 1386 Cellular Automaton

题目:点击打开链接 题意:一个细胞自动机包含n个格子,每个格子的值都会变成它距离不超过d的所有格子的值,求最后的结果 思路:这个是循环矩阵,可以用O(n^2)的时间过掉 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 505; int

HDU 5895 Mathematician QSC(矩阵乘法+循环节降幂+除法取模小技巧+快速幂)

传送门:HDU 5895 Mathematician QSC 这是一篇很好的题解,我想讲的他基本都讲了http://blog.csdn.net/queuelovestack/article/details/52577212 [分析]一开始想简单了,对于a^x mod p这种形式的直接用欧拉定理的数论定理降幂了 结果可想而知,肯定错,因为题目并没有保证gcd(x,s+1)=1,而欧拉定理的数论定理是明确规定的 所以得另谋出路 那么网上提供了一种指数循环节降幂的方法 具体证明可以自行从网上找一找 有

[NOI2011] 兔农 矩阵乘法,矩阵的等比数列求和

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; ll n,p; ll k; #define N 4000000 ll a[N],fr[N]; struct sq{ ll a[3][3]; sq(){memset(a,0,sizeof(a));} sq operator*(sq

矩阵乘法及矩阵链乘的快速幂优化

一.矩阵乘法 1 struct datatype 2 { 3 int a[2][2]; 4 }; 5 datatype multiple(datatype x,datatype y) 6 { 7 datatype res; 8 memset(res.a,0,sizeof(res.a)); 9 for(int i=0;i<=1;i++) 10 { 11 for(int j=0;j<=1;j++) 12 { 13 for(int k=0;k<=1;k++) 14 { 15 res.a[i][

蓝桥杯 BASIC_17 矩阵乘法 (矩阵快速幂)

问题描述 给定一个N阶矩阵A,输出A的M次幂(M是非负整数) 例如: A = 1 2 3 4 A的2次幂 7 10 15 22 输入格式 第一行是一个正整数N.M(1<=N<=30, 0<=M<=5),表示矩阵A的阶数和要求的幂数 接下来N行,每行N个绝对值不超过10的非负整数,描述矩阵A的值 输出格式 输出共N行,每行N个整数,表示A的M次幂所对应的矩阵.相邻的数之间用一个空格隔开 样例输入 2 2 1 2 3 4 样例输出 7 10 15 22 这道题题目很简单,而且数据量也很

矩阵乘法以及矩阵快速幂模板

两矩阵 A * B ,当 A 的行数等于 B 的列数时,A * B 合法,结果如下: 1 #include<stdio.h> 2 #include<string.h> 3 4 struct mat{ 5 int r,c; //r即row,矩阵行数:c即column,矩阵列数 6 int m[10][10]; //矩阵 7 }; 8 9 mat MatMul(mat m1,mat m2){ //仅当m1.r==m2.c时可以相乘,相乘时可加模运算 10 mat tmp; 11 tmp

51nod 1137矩阵乘法【矩阵】

1137 矩阵乘法 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出2个N * N的矩阵M1和M2,输出2个矩阵相乘后的结果. Input 第1行:1个数N,表示矩阵的大小(2 <= N <= 100) 第2 - N + 1行,每行N个数,对应M1的1行(0 <= M1[i] <= 1000) 第N + 2 - 2N + 1行,每行N个数,对应M2的1行(0 <= M2[i] <= 1000) Output 输出共N行,

矩阵乘法——多矩阵连乘请记得加括号

数学上,矩阵乘法满足结合率,因此  $ (AB)C=A(BC)$  在计算结果上是一样的. 但是在计算效率上,它们是不一样的. 举个简单的例子 $\alpha {\alpha ^T}\alpha$ $(\alpha {\alpha ^T})\alpha$需要$2{n^2}$次运算 而 $\alpha ({\alpha ^T}\alpha )$只要$2n$次运算 因此,在进行多矩阵连乘时,需要加上适当的括号.