设为首页 加入收藏

TOP

poj 3150 Cellular Automaton
2014-11-23 21:42:21 来源: 作者: 【 】 浏览:7
Tags:poj 3150 Cellular Automaton
思路: 矩阵快速幂
分析:
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  
#include  
#include  
#include  
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;  
}  


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇POJ 1472 Coins (多重背包+滚动.. 下一篇UVA 103 Stacking Boxes (dp + DA..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·【C语言】动态内存管 (2025-12-27 06:23:20)
·C语言中的内存管理 - (2025-12-27 06:23:16)
·C语言指南:C语言内 (2025-12-27 06:23:14)
·Redis on AWS:Elast (2025-12-27 04:19:30)
·在 Spring Boot 项目 (2025-12-27 04:19:27)