zoukankan      html  css  js  c++  java
  • poj 3150 Cellular Automaton 矩阵快速幂

    题目链接:

    http://poj.org/problem?id=3150

    题意:

    一个环上有n个数,定义一种操作将它和它距离小于d的数加和再模m。每次操作刷新所有数。问k次之后都将变成什么数?

    思路:

    http://blog.csdn.net/lin375691011/article/details/38493267

    矩阵快速幂加速递推。

    按照正常思路第i次操作是基于第i-1次操作完成的,也就是说要完成第i次操作需要先完成第i-1次。

    但是用于矩阵之后可以直接推出第i次与第一次之间是什么关系。

    这个矩阵是可以通过矩阵快速幂得出的。

    如果你注意关系矩阵的建立的话,你会发现这么一个规律。对于d=1来说:
    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]

    也就是说我们只需要存第一行就行了。每次矩阵乘法也只需要得出第一行就行了。

    代码:

     1 #include <iostream>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <cstdio>
     5 using namespace std;
     6 typedef long long ll;
     7 #define MS(a) memset(a,0,sizeof(a))
     8 #define MP make_pair
     9 #define PB push_back
    10 const int INF = 0x3f3f3f3f;
    11 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
    12 inline ll read(){
    13     ll x=0,f=1;char ch=getchar();
    14     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    15     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    16     return x*f;
    17 }
    18 //////////////////////////////////////////////////////////////////////////
    19 const int maxn = 1e5+10;
    20 
    21 struct matrix{
    22     ll m[505];
    23     void clear(){
    24         MS(m);
    25     }
    26 }r,a,ans;
    27 
    28 int n,mod,d,k;
    29 
    30 matrix mul(matrix a,matrix b){
    31     matrix re;
    32     re.clear();
    33     int p;
    34     for(int i=0; i<n; i++){
    35         p = (n-i)%n;
    36         for(int j=0; j<n; j++){
    37             re.m[i] = (re.m[i]+a.m[j]*b.m[p])%mod;
    38             p = (p+1)%n;
    39         }
    40     }
    41     return re;
    42 }
    43 
    44 matrix qpow(int k){
    45     matrix e;
    46     e.clear();
    47     e.m[0] = 1;
    48     while(k){
    49         if(k & 1) e = mul(e,a);
    50         a = mul(a,a);
    51         k >>= 1;
    52     }
    53     return e;
    54 }
    55 
    56 int main(){
    57     while(cin>>n>>mod>>d>>k){
    58         a.clear(); r.clear();
    59         for(int i=0; i<n; i++){
    60             r.m[i] = read();
    61         }
    62 
    63         for(int i=0; i<n; i++){
    64             if(i<=d || (n-i)<=d) a.m[i] = 1;
    65             else a.m[i] = 0;
    66         }
    67 
    68         a = qpow(k);
    69 
    70         ans = mul(r,a);
    71 
    72         for(int i=0; i<n; i++){
    73             if(i) printf(" ");
    74             cout << ans.m[i];
    75         }
    76         puts("");
    77     }
    78 
    79     return 0;
    80 }
  • 相关阅读:
    .VC中的Attach和Detach
    virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
    用API OleLoadPicture通过IStream来加载JPG、GIF格式的图片
    .OnNcHitTest
    线性规划与网络流24题索引
    线性规划与网络流24题 17运输问题
    网络流24题 21最长k可重区间集问题
    网络流16数字梯形问题
    网络流24题 20深海机器人问题
    网络流24题 19负载平衡问题
  • 原文地址:https://www.cnblogs.com/yxg123123/p/6837633.html
Copyright © 2011-2022 走看看