• poj 3150 Cellular Automaton


    点击打开poj 3150

    思路: 矩阵快速幂

    分析:

    1 题目给定n个数每个数在0~m-1之内,题目规定两个数之间的距离为min(|i-j| , n-|i-j|)。现在给定d和k,表示做k次的变换,每一次变换过后每个数变成了一个新的数。这个新的数等于和它距离小于等于d的所有数的和%m

    2 这题和之前做的两道题很像hdu2276 和 FZU1692,都是属于循环同构的问题

       那么我们先来看一下每个数在做一次变换过后变成什么。因为要距离小于等于d,第一种|i-j| = d , 则j = i+d , 第二种情况n-|i-j| = d , 因此 j = n-d+i 。

       第一个数等于 = num[1]+num[2]+....+num[d+1] + num[n-d+1]+...+num[n]

       第二个数等于 = num[2]+....+num[d+2] + num[n-d+2]+...+num[n]

       ..............................................................................................................

    3 因为这里的矩阵是循环同构的,因此我们只要求出第一行,剩下的我们就可以根据前一行推出。这样就把矩阵的乘法的复杂度降到了O(n^2)


    代码:

    /************************************************
     * By: chenguolin                               * 
     * Date: 2013-08-31                             *
     * Address: http://blog.csdn.net/chenguolinblog *
     ************************************************/
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    typedef long long int64;
    const int N = 505; 
    
    int n , MOD , d , k;
    int arr[N];
    
    struct Matrix{
        int64 mat[N][N];
        Matrix operator*(const Matrix &m)const{
            Matrix tmp;
            for(int i = 1 ; i <= n ; i++){
                tmp.mat[1][i] = 0;
                for(int j = 1 ; j <= n ; j++)
                    tmp.mat[1][i] += mat[1][j]*m.mat[j][i]%MOD;
                tmp.mat[1][i] %= MOD;
            }
            for(int i = 2 ; i <= n ; i++){
                tmp.mat[i][1] = tmp.mat[i-1][n];
                for(int j = 2 ; j <= n ; j++)
                    tmp.mat[i][j] = tmp.mat[i-1][(j-1+n)%n];
            }
            return tmp; 
        }
    };
    
    void init(Matrix &m){
        memset(m.mat , 0 , sizeof(m.mat));
        for(int i = 1 ; i <= d+1 ; i++)
            m.mat[1][i] = 1;
        for(int i = n-d+1 ; i <= n ; i++)
            m.mat[1][i] = 1;
        for(int i = 2 ; i <= n ; i++){
            m.mat[i][1] = m.mat[i-1][n];
            for(int j = 2 ; j <= n ; j++)
                m.mat[i][j] = m.mat[i-1][(j-1+n)%n];
        }
    }
    
    void Pow(Matrix &m){
        Matrix ans;
        memset(ans.mat , 0 , sizeof(ans.mat));
        for(int i = 1 ; i <= n ; i++)
            ans.mat[i][i] = 1;
        while(k){
            if(k&1)
                ans = ans*m;
            k >>= 1;
            m = m*m;
        }
        for(int i = 1 ; i <= n ; i++){
            int64 sum = 0;
            for(int j = 1 ; j <= n ; j++)
                sum += ans.mat[i][j]*arr[j]%MOD;
            if(i > 1) printf(" ");
            printf("%lld" , sum%MOD);
        }
        puts("");
    }
    
    int main(){
        Matrix m;
        while(scanf("%d" , &n) != EOF){
            scanf("%d%d%d" , &MOD , &d , &k);
            for(int i = 1 ; i <= n ; i++)
                scanf("%d" , &arr[i]);
            init(m);
            Pow(m);
        }    
        return 0;
    }
    
    



  • 相关阅读:
    Oracle架构实现原理、含五大进程解析(图文详解)
    Oracle架构实现原理、含五大进程解析(图文详解)
    mysqldump --flush-logs
    mysql dump 参数
    Windows 8.1 PLSQL_32连接到RHEL6.1 Oracle10gr2_64
    Windows 8.1 PLSQL_32连接到RHEL6.1 Oracle10gr2_64
    echarts-单柱状图
    echarts-all.js:1 Dom’s width & height should be ready before init.
    如果是在有master上开启了该参数,记得在slave端也要开启这个参数(salve需要stop后再重新start),否则在master上创建函数会导致replaction中断。
    mysql 创建函数 error Code: 1227. Access denied;
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3294022.html
Copyright © 2020-2023  润新知