POJ 3150 Cellular Automaton(矩阵乘法+二分)
2014-07-28 20:44
239 查看
题目链接
题意 : 给出n个数形成环形,一次转化就是将每一个数前后的d个数字的和对m取余,然后作为这个数,问进行k次转化后,数组变成什么。
思路 :下述来自here
首先来看一下Sample里的第一组数据。
1 2 2 1 2
经过一次变换之后就成了
5 5 5 5 4
它的原理就是
a0 a1 a2 a3 a4
->
(a4+a0+a1) (a0+a1+a2) (a1+a2+a3) (a2+a3+a4) (a3+a4+a0)
如果用矩阵相乘来描述,那就可以表述为1xN和NxN的矩阵相乘,结果仍为1xN矩阵
a = 1 2 2 1 2
b =
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
a * b = 5 5 5 5 4
所以最终结果就是:a * (b^k)
线性代数不合格的同鞋表示压力很大。。
对一个NxN矩阵求k次方,而且这个k很大,N也不小,怎么办?
所以有高手观察到了,这个矩阵长得有点特殊,可以找到一些规律:
b^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]
b^2 =
[3, 2, 1, 1, 2]
[2, 3, 2, 1, 1]
[1, 2, 3, 2, 1]
[1, 1, 2, 3, 2]
[2, 1, 1, 2, 3]
b^3 =
[7, 6, 4, 4, 6]
[6, 7, 6, 4, 4]
[4, 6, 7, 6, 4]
[4, 4, 6, 7, 6]
[6, 4, 4, 6, 7]
b^4 =
[19, 17, 14, 14, 17]
[17, 19, 17, 14, 14]
[14, 17, 19, 17, 14]
[14, 14, 17, 19, 17]
[17, 14, 14, 17, 19]
发现神马没有。就是无论是b的几次幂,都符合A[i][j] = A[i-1][j-1]
高手说是这样推倒出来地:
““”
利用矩阵A,B具有a[i][j]=A[i-1][j-1],B[i][j]=B[i-1][j-1](i-1<0则表示i-1+n,j-1<0则表示j-1+n)
我们可以得出矩阵C=a*b也具有这个性质
C[i][j]=sum(A[i][t]*B[t][j])=sum(A[i-1][t-1],B[t-1][j-1])=sum(A[i-1][t],B[t][j-1])=C[i-1][j-1]
“”“
这样就可以开一个N大小的数组来存放每次计算的结果了。而没必要用NxN。
N的问题解决了,但是k还是很大,怎么办?
这时候可以用二分法来求b^k
b^k = b^1 * b^4 * b^16 。。。
View Code
计算过程中,必定会出现数字大于M的情况。
切记 x*y = (x%M)*(y%M)
题意 : 给出n个数形成环形,一次转化就是将每一个数前后的d个数字的和对m取余,然后作为这个数,问进行k次转化后,数组变成什么。
思路 :下述来自here
首先来看一下Sample里的第一组数据。
1 2 2 1 2
经过一次变换之后就成了
5 5 5 5 4
它的原理就是
a0 a1 a2 a3 a4
->
(a4+a0+a1) (a0+a1+a2) (a1+a2+a3) (a2+a3+a4) (a3+a4+a0)
如果用矩阵相乘来描述,那就可以表述为1xN和NxN的矩阵相乘,结果仍为1xN矩阵
a = 1 2 2 1 2
b =
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
a * b = 5 5 5 5 4
所以最终结果就是:a * (b^k)
线性代数不合格的同鞋表示压力很大。。
对一个NxN矩阵求k次方,而且这个k很大,N也不小,怎么办?
所以有高手观察到了,这个矩阵长得有点特殊,可以找到一些规律:
b^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]
b^2 =
[3, 2, 1, 1, 2]
[2, 3, 2, 1, 1]
[1, 2, 3, 2, 1]
[1, 1, 2, 3, 2]
[2, 1, 1, 2, 3]
b^3 =
[7, 6, 4, 4, 6]
[6, 7, 6, 4, 4]
[4, 6, 7, 6, 4]
[4, 4, 6, 7, 6]
[6, 4, 4, 6, 7]
b^4 =
[19, 17, 14, 14, 17]
[17, 19, 17, 14, 14]
[14, 17, 19, 17, 14]
[14, 14, 17, 19, 17]
[17, 14, 14, 17, 19]
发现神马没有。就是无论是b的几次幂,都符合A[i][j] = A[i-1][j-1]
高手说是这样推倒出来地:
““”
利用矩阵A,B具有a[i][j]=A[i-1][j-1],B[i][j]=B[i-1][j-1](i-1<0则表示i-1+n,j-1<0则表示j-1+n)
我们可以得出矩阵C=a*b也具有这个性质
C[i][j]=sum(A[i][t]*B[t][j])=sum(A[i-1][t-1],B[t-1][j-1])=sum(A[i-1][t],B[t][j-1])=C[i-1][j-1]
“”“
这样就可以开一个N大小的数组来存放每次计算的结果了。而没必要用NxN。
N的问题解决了,但是k还是很大,怎么办?
这时候可以用二分法来求b^k
b^k = b^1 * b^4 * b^16 。。。
//3150 #include <cstdio> #include <cstring> #include <iostream> #define LL long long using namespace std ; int n,m , d , k ; LL a[1010] ,b[1010] ; void multi(LL *c,LL *d) { LL x[1010] ; for(int i = 0 ; i < n ; i++) { x[i] = 0 ; for(int j = 0 ; j < n ; j++) x[i] += c[j] * d[i >= j ? (i - j) : (n + i - j)] ;//防止是负数,形成环 } for(int i = 0 ; i < n ; i++) d[i] = x[i] % m ; } int main() { while(cin >> n >> m >> d >> k ){ for(int i = 0 ; i < n ; i++) cin >> a[i] ; b[0] = 1 ; for(int i = 1 ; i <= d ; i++) b[i] = b[n - i] = 1 ; while(k) { if(k & 1)//奇数 multi(b,a) ; multi(b,b) ; k >>= 1 ; } for(int i = 0 ; i < n ; i++) if(i == n-1) printf("%I64d\n",a[i]) ; else printf("%I64d ",a[i]) ; } return 0 ; }
View Code
计算过程中,必定会出现数字大于M的情况。
切记 x*y = (x%M)*(y%M)
相关文章推荐
- POJ_3150_矩阵快速幂+循环矩阵的乘法
- 【POJ 3233】【二分+矩阵乘法】Matrix Power Series【求S = A + A2 + A3 + … + Ak】
- [POJ 3150] Cellular Automaton (矩阵高速幂 + 矩阵乘法优化)
- POJ 3233 Matrix Power Series (矩阵乘法+快速幂+等比二分求和) -
- POJ 3233 Matrix Power Series 二分+矩阵乘法
- POJ_3150_矩阵快速幂+循环矩阵的乘法
- T解 POJ-3233 [矩阵快速幂][矩阵乘法][二分求解]
- poj 3233 (矩阵乘法+二分+递归)
- POJ 3233 Matrix Power Series 二分+矩阵乘法
- 【POJ】3150 Cellular Automaton(矩阵乘法+特殊的技巧)
- POJ 3233 Matrix Power Series (矩阵快速幂+二分)
- POJ 3233 Matrix Power Series (矩阵快速幂+二分求解)
- BZOJ 2738 矩阵乘法 整体二分+二维树状数组
- hdu 1588 Gauss Fibonacci(矩阵乘法,二分)
- poj 3323 Matrix Power Series (矩阵乘法 非递归形式)
- poj 3613 floyd+二分矩阵相乘(快速幂)
- bzoj2738 矩阵乘法(整体二分+二维树状数组)
- pku 3150(修改后的矩阵乘法)
- POJ 3420 矩阵乘法
- poj 3233 Matrix Power Series(矩阵二分,高速幂)