zoukankan      html  css  js  c++  java
  • poj 3150 Cellular Automaton(矩阵连乘)

    好久没写博了,最近都没怎么做poj,总是找些三体做做,没局限于哪些知识点,只是想锻炼一下自己独立思考的能力。

    好了,废话少说,还是来说说这道题吧。

    题意:给出M个数形成环形,一次转化就是将每一个数前后的d个数字的和对m取余,然后作为这个数,问进行k次后的数组是什么。

    思路:呃,其实看完这题后,首先想到的事模拟,但是这题的数据量很大,然后就没招了。看了看了discuss了的讨论,看到他们都在讨论矩阵连乘的问题,然后向了半天,貌似有点头绪了,但是不清晰,然后看了解题报告,脑中的想法一下就清晰了,不过当时不知道N*N的矩阵连乘会超时,后来看了别人的优化,才知道自己差的还很多。

    说下主要思想吧,对于样例1来说,a[0] = (a[0]*1)+(a[1]*1)+a[2]*0)+(a[3]*0)+(a[4]*1),这样得到一个N*N 的系数矩阵p,即:

    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

    然后就是用二分求p^k,不过这样做也会超时,所以要找下这个矩阵的规律,做些优化,不过这个规律不是我自己找出来的,就不多说了,可以看一下这个博客,里面讲的很清楚:http://www.cppblog.com/varg-vikernes/archive/2011/02/08/139804.html

    代码:

    View Code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <math.h>
    #define  N 505
    using namespace std ;
    
    typedef long long ll ;
    
    ll a[N] , p[N] ;
    
    int n , m , d , k ;
    
    void mult( ll a[] , ll b[] )
    {
        ll c[N] ;
        int i , j;
        for ( i = 0 ; i < n ; i++ )
        {
            c[i] = 0;
            for ( j = 0 ; j < n ; j++ )
            {
                c[i] += a[j] * b[i>=j?(i-j) : (n+i-j)] ;
            }
        }
        for ( i = 0 ; i < n ; i++ )
        b[i] = c[i] % m ;
    }
    
    int main()
    {
        int i ;
    
        scanf ( "%d%d%d%d" , &n , &m , &d , &k);
        {
            for ( i = 0 ; i < n ; i++ )
            cin>>a[i] ;
    
            for ( p[0] = i = 1 ; i<= d ; ++i )
            p[i] = p[n-i] = 1 ;
    
            while ( k )//二分法求p^k
            {
                if( k & 1 )//k为奇数
                mult( p , a );
                mult( p , p );//k为偶数
                k>>=1 ;
            }
    
            for( i = 0 ; i < n ; i++ )
            {
                if ( i )
                cout<<" "<<( a[i] % m );
                else
                cout<<(a[i] % m ) ;
            }
            cout<<endl;
        }
        return 0 ;
    }
  • 相关阅读:
    redis 高级
    redis连接
    redis脚本
    Redis事务
    redis发布订阅
    加一
    C语言从代码中加载动态链接库
    GCC编译器
    Vim编辑器基础
    Linux用户的创建与授权及修改密码
  • 原文地址:https://www.cnblogs.com/misty1/p/2686876.html
Copyright © 2011-2022 走看看