LA 3704 (矩阵快速幂 循环矩阵) Cellular Automaton

将这n个格子看做一个向量,每次操作都是一次线性组合,即vn+1 = Avn,所求答案为Akv0

A是一个n*n的矩阵,比如当n=5,d=1的时候:

不难发现,A是个循环矩阵,也就是将某一行所有元素统一向右移动一位便得到下一行。

而且循环矩阵相乘仍然是循环矩阵,所以只要求出Ak的第一行就行了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5
 6 const int maxn = 500 + 10;
 7 typedef long long Vector[maxn];
 8
 9 int n, m, d, k;
10
11 inline int value(Vector A, int i, int j)
12 {//循环矩阵A(i, j)的值
13     return A[(((j-i)%n)+n)%n];
14 }
15
16 void matrix_mul(Vector A, Vector B, Vector res)
17 {
18     Vector C;
19     memset(C, 0, sizeof(C));
20     for(int j = 0; j < n; j++)
21         for(int k = 0; k < n; k++)
22             C[j] = (C[j] + A[k] * value(B, k, j)) % m;
23     memcpy(res, C, sizeof(C));
24 }
25
26 void matrix_pow(Vector A, int n, Vector res)
27 {
28     Vector a, r;
29     memcpy(a, A, sizeof(a));
30     memset(r, 0, sizeof(r));
31     r[0] = 1;
32     while(n)
33     {
34         if(n&1) matrix_mul(r, a, r);
35         n >>= 1;
36         matrix_mul(a, a, a);
37     }
38     memcpy(res, r, sizeof(r));
39 }
40
41 void solve(Vector A, Vector v, Vector res)
42 {
43     Vector B;
44     memset(B, 0, sizeof(B));
45     for(int i = 0; i < n; i++)
46         for(int j = 0; j < n; j++)
47             B[i] = (B[i] + value(A, i, j) * v[j]) % m;
48     memcpy(res, B, sizeof(B));
49 }
50
51 int main()
52 {
53     //freopen("in.txt", "r", stdin);
54
55     while(cin >> n >> m >> d >> k)
56     {
57         Vector A, v;
58         for(int i = 0; i < n; i++) cin >> v[i];
59         memset(A, 0, sizeof(A));
60         for(int p = -d; p <= d; p++)
61         {
62             int x = ((p%n)+n)%n;
63             A[x] = 1;
64         }
65         /*for(int i = 0; i < n; i++)
66         {
67             for(int j = 0; j < n; j++)
68                 printf("%d ", value(A, i, j));
69             printf("\n");
70         }*/
71         matrix_pow(A, k, A);
72         solve(A, v, v);
73         for(int i = 0; i < n; i++)
74         {
75             if(i) printf(" ");
76             cout << v[i];
77         }
78         printf("\n");
79     }
80
81     return 0;
82 }

代码君

时间: 2024-08-27 23:44:52

LA 3704 (矩阵快速幂 循环矩阵) Cellular Automaton的相关文章

HDU 1575 &amp;&amp; 1757 矩阵快速幂&amp;&amp;构造矩阵入门

HDU 1575 Tr A Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2912    Accepted Submission(s): 2167 Problem Description A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973. Input 数据的第一行是一个T,表示有T组数据.每组

算法初步:快速乘,快速幂,矩阵快速幂

原创 by zoe.zhang 在刷题的时候遇到了问题,就是当循环或者递推的次数非常大的情况下获取一定结果,这个时候如果作普通运算,那么很容易就超时了,而且有时候结果也大得超范围了,即使是long long类型的也放不下,然后给了提示说是运用快速幂的思想.所以这里对快速幂做了一点思考和探讨. 1.快速乘,快速幂,矩阵快速幂三者的关系 不管是快速乘,还是快速幂算法,实际上都包含了分解问题的思想在里面,将O(n)的复杂度降到O(lgn).学习的时候,一般学习快速幂算法,再由此推广去解决矩阵快速幂问题

算法笔记--矩阵快速幂

写的不错的博客:http://www.cnblogs.com/yan-boy/archive/2012/11/29/2795294.html 优点:根据数列递推式快速计算数列an的值(当n很大时) 步骤:由数列递推式构造矩阵,然后用矩阵快速幂计算矩阵的幂. 构造矩阵:对于an =x*an-1 +y*an-2 ,可以构造矩阵为: [an ,an-1]=[an-1 ,an-2]*A A=[x 1 y 0]; 矩阵快速幂模板: #include<iostream> #include<cstri

Fibonacci----poj3070(矩阵快速幂, 模板)

题目链接:http://poj.org/problem?id=3070 . 就是斐波那契的另一种表示方法是矩阵的幂: 所以是矩阵快速幂:矩阵快速幂学习 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include<math.h> using namespace std; #define N 10 struct node { int a[

快速幂计算(整数快速幂/矩阵快速幂)

库函数pow是用朴素算法对浮点型数据进行幂运算的,时间复杂度为o(n),计算比较大的数可能会超时和数据溢出: //*************快速幂计算**************************************** 朴素算法实现: ll get_pow(ll x, ll n)  //** (这里的n要求不小于0,如果n小于0则令n=-n,并且最终返回1.0/ans即可){    ll ans=1;    while(n--)    {        ans*=x%MAX;    

矩阵快速幂小结

矩阵 并不想扯什么高端线代的内容因为我也不会 定义 由$n \times m$个数$a_{ij}$排成的$n$行$m$列的数表称为$n$行$m$列的矩阵,简称$n \times m$矩阵. $$A =\begin{bmatrix}a_{11} & a_{12} & \dots a_{1m} \\ a_{21}, & \dots & \dots \\ a_{31}, & \dots & \dots \\ a_{41} & \dots & a_{

POJ 3233 Matrix Power Series 【经典矩阵快速幂+二分】

任意门:http://poj.org/problem?id=3233 Matrix Power Series Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 28619   Accepted: 11646 Description Given a n × n matrix A and a positive integer k, find the sum S = A + A2 + A3 + - + Ak. Input The

Uva10870 Recurrences(矩阵快速幂)

题目 考虑递推关系式\(f(n)=a1*f(n-1)+a2*f(n-2)+....+ad*f(n-d)\),计算f(n)%m [输入格式] 输入包含多组测试数据.每组数据第一行为三个整数d,n,m(1<=d<=15,1<=n<=2^31-1,1<=m<=46340).第二行包含d个非负整数a1,a2.....ad.第三行为d个非负整数f(1),f(2).....f(d).这些数字均不超过2^31-1.输入结束的标志是d=n=m=0. [输出格式] 对于每组数据,输出f(

LA 3704细胞自动机——循环矩阵&amp;&amp;矩阵快速幂

题目 一个细胞自动机包含 $n$ 个格子,每个格子的取值为 $0 \sim m-1$.给定距离 $d$,则每次操作是将每个格子的值变为到它的距离不超过 $d$ 的所有格子的在操作之前的值的和除以 $m$ 的余数.给出 $n, m, d, k$ 和自动机各个格子的初始值.你的任务是计算 $k$ 次操作以后各格子的值.($1 \leq n\leq 500, 1 \leq m\leq 10^6, 0 \leq d\leq n/2, 1\leq k\leq 10^7$). 分析 如果我们把 $t$ 次操