zoukankan      html  css  js  c++  java
  • poj 3150 Cellular Automaton

    首先来看一下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 。。。

    计算过程中,必定会出现数字大于M的情况。
    切记 x*y = (x%M)*(y%M)

    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    #include<iomanip>
    #include<cmath>
    #include<stdlib.h>
    #include<cstring>
    #include<vector>
    #define ll __int64
    #define pi acos(-1.0)
    #define Max 50000
    using namespace std;
    ll bn[501],temp[501];
    int m,n,d,k;
    void mul(ll a[],ll b[])
    {
        int i,j;
        ll ans[501];
        for (i=0;i<n;i++)
        for (j=ans[i]=0;j<n;j++)
            ans[i] += a[j]*b[i>=j?(i-j):(n+i-j)];
        for (i=0;i<n;b[i]=ans[i++]%m);
    }
    int main(){
        int i;
        scanf("%d%d%d%d",&n,&m,&d,&k);
        for (i=0;i<n;i++)
            scanf("%I64d",&bn[i]);
        for (temp[0]=i=1;i<=d;i++)
            temp[i]=temp[n-i]=1;
        while(k){
            if (k&1) mul(temp,bn);
            mul(temp,temp);
            k>>=1;
        }
        for(i=0;i<n;i++)
            if(i) printf(" %I64d",bn[i]);
            else printf("%I64d",bn[i]);
        printf("");
        return 0;
    }
    View Code
  • 相关阅读:
    ubuntu的php7与apache2的环境搭建
    git服务器搭建post-receive 钩子部署服务端代码
    node redis安装与使用
    微信小程序坑集
    微信小程序登录
    mobx react
    react-native-router-flux 下部导航
    java
    java
    java
  • 原文地址:https://www.cnblogs.com/xin-hua/p/3223984.html
Copyright © 2011-2022 走看看