首页 > 代码库 > POJ3150—Cellular Automaton(循环矩阵)

POJ3150—Cellular Automaton(循环矩阵)

题目链接:http://poj.org/problem?id=3150

题目意思:有n个数围成一个环,现在有一种变换,将所有距离第i(1<=i<=n)个数小于等于d的数加起来,对m取余,现在要求将所有的数都变换k次,得到的n个数的值。

思路:构造一个循环矩阵,以下这个矩阵是以样例1为例的循环矩阵。

1 1 0 0 1
1 1 1 0 0
0 1 1 1 0
0 0 1 1 1
1 0 0 1 1

我们发现n尽然达到了500,复杂度是n^3logk,过不了,我们发现这个矩阵长得很奇葩,每一行都是上一行后移一位得到,所以我们每个矩阵可以n^2算出一行,然后通过平移得到全部的矩阵。从而把n^3的矩阵乘法变成n^2,复杂度是n^2logk,就可以AC了,其他没有什么奇怪的操作。第一道循环矩阵题,算是涨姿势了,循环矩阵乘法模板记住了。

代码:

技术分享
 1 //Author: xiaowuga
 2 #include<iostream>
 3 #include<cstring>
 4 #define maxx INT_MAX
 5 #define minn INT_MIN
 6 #define inf 0x3f3f3f3f
 7 #define N  505
 8 using namespace std;
 9 long long MOD;
10 typedef long long ll;
11 long long  n,size;//第n项,矩阵大小
12  long long f[550];
13 struct Matrix{
14     long long mat[N][N];
15     void clear(){
16         memset(mat,0,sizeof(mat));
17     }
18     Matrix operator * (const Matrix & m) const{
19         Matrix tmp;
20         tmp.clear();
21         for(int i=0;i<size;i++){
22             for(int j=0;j<size;j++){
23                 tmp.mat[0][i]+=mat[0][j]*m.mat[j][i]%MOD;
24             }
25             tmp.mat[0][i]%=MOD;
26         }
27         for(int i=1;i<size;i++){
28             for(int j=0;j<size;j++)
29                 tmp.mat[i][j]=tmp.mat[i-1][(j+size-1)%size];
30         }
31         return tmp;
32     }
33 }M,ANS;
34 Matrix ans;
35 void POW(Matrix m,ll k){
36     memset(ans.mat,0,sizeof(ans.mat));
37     for(int i=0;i<size;i++) ans.mat[i][i]=1;
38     while(k){
39         if(k&1) ans=ans*m;
40         k/=2;
41         m=m*m;
42     }
43      long long sum;
44         for(int i=0;i<size;i++){
45             sum=0;
46             for(int j=0;j<size;j++){
47                 sum+=ans.mat[i][j]*f[j]%MOD;
48             }
49             if(i==0) cout<<sum%MOD;
50             else cout<<" "<<sum%MOD;
51         }
52         cout<<endl;
53 }
54 int main() {
55     ios::sync_with_stdio(false);cin.tie(0);
56     long long d;
57     while(cin>>size>>MOD>>d>>n){
58         M.clear();
59         for(int i=0;i<size;i++) cin>>f[i];
60         for(int i=0;i<size;i++){
61             M.mat[i][i]=1;
62             for(int j=1;j<=d;j++){
63                 M.mat[i][(i+j+size)%size]=1;
64                 M.mat[i][(i-j+size)%size]=1;
65             }
66         }
67         for(int i=0;i<size;i++){
68             for(int j=0;j<size;j++) cout<<M.mat[i][j]<< ;
69             cout<<endl;
70         }
71         POW(M,n);
72     }
73     return 0;
74 }
View Code

 

POJ3150—Cellular Automaton(循环矩阵)