程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> poj 3150 Cellular Automaton

poj 3150 Cellular Automaton

編輯:C++入門知識

思路: 矩陣快速冪 分析: 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;  
}  

 


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved