现在的位置: 首页 > 综合 > 正文

poj 3150 Cellular Automaton

2017年09月27日 ⁄ 综合 ⁄ 共 2716字 ⁄ 字号 评论关闭
分类: ACM_数学-矩阵快速幂 318人阅读 评论(0) 收藏 举报

点击打开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)


代码:

  1. /************************************************ 
  2.  * By: chenguolin                               *  
  3.  * Date: 2013-08-31                             * 
  4.  * Address: http://blog.csdn.net/chenguolinblog * 
  5.  ************************************************/  
  6. #include<cstdio>  
  7. #include<cstring>  
  8. #include<iostream>  
  9. #include<algorithm>  
  10. using namespace std;  
  11.   
  12. typedef long long int64;  
  13. const int N = 505;   
  14.   
  15. int n , MOD , d , k;  
  16. int arr[N];  
  17.   
  18. struct Matrix{  
  19.     int64 mat[N][N];  
  20.     Matrix operator*(const Matrix &m)const{  
  21.         Matrix tmp;  
  22.         for(int i = 1 ; i <= n ; i++){  
  23.             tmp.mat[1][i] = 0;  
  24.             for(int j = 1 ; j <= n ; j++)  
  25.                 tmp.mat[1][i] += mat[1][j]*m.mat[j][i]%MOD;  
  26.             tmp.mat[1][i] %= MOD;  
  27.         }  
  28.         for(int i = 2 ; i <= n ; i++){  
  29.             tmp.mat[i][1] = tmp.mat[i-1][n];  
  30.             for(int j = 2 ; j <= n ; j++)  
  31.                 tmp.mat[i][j] = tmp.mat[i-1][(j-1+n)%n];  
  32.         }  
  33.         return tmp;   
  34.     }  
  35. };  
  36.   
  37. void init(Matrix &m){  
  38.     memset(m.mat , 0 , sizeof(m.mat));  
  39.     for(int i = 1 ; i <= d+1 ; i++)  
  40.         m.mat[1][i] = 1;  
  41.     for(int i = n-d+1 ; i <= n ; i++)  
  42.         m.mat[1][i] = 1;  
  43.     for(int i = 2 ; i <= n ; i++){  
  44.         m.mat[i][1] = m.mat[i-1][n];  
  45.         for(int j = 2 ; j <= n ; j++)  
  46.             m.mat[i][j] = m.mat[i-1][(j-1+n)%n];  
  47.     }  
  48. }  
  49.   
  50. void Pow(Matrix &m){  
  51.     Matrix ans;  
  52.     memset(ans.mat , 0 , sizeof(ans.mat));  
  53.     for(int i = 1 ; i <= n ; i++)  
  54.         ans.mat[i][i] = 1;  
  55.     while(k){  
  56.         if(k&1)  
  57.             ans = ans*m;  
  58.         k >>= 1;  
  59.         m = m*m;  
  60.     }  
  61.     for(int i = 1 ; i <= n ; i++){  
  62.         int64 sum = 0;  
  63.         for(int j = 1 ; j <= n ; j++)  
  64.             sum += ans.mat[i][j]*arr[j]%MOD;  
  65.         if(i > 1) printf(" ");  
  66.         printf("%lld" , sum%MOD);  
  67.     }  
  68.     puts("");  
  69. }  
  70.   
  71. int main(){  
  72.     Matrix m;  
  73.     while(scanf("%d" , &n) != EOF){  
  74.         scanf("%d%d%d" , &MOD , &d , &k);  
  75.         for(int i = 1 ; i <= n ; i++)  
  76.             scanf("%d" , &arr[i]);  
  77.         init(m);  
  78.         Pow(m);  
  79.     }      
  80.     return 0;  
  81. }  

抱歉!评论已关闭.