zoukankan      html  css  js  c++  java
  • poj-3150-Cellular Automation

    poj-3150-Cellular Automation

    Cellular Automaton
    Time Limit: 12000MS   Memory Limit: 65536K
    Total Submissions: 3795   Accepted: 1557
    Case Time Limit: 2000MS

    Description

    cellular automaton is a collection of cells on a grid of specified shape that evolves through a number of discrete time steps according to a set of rules that describe the new state of a cell based on the states of neighboring cells. The order of the cellular automaton is the number of cells it contains. Cells of the automaton of order n are numbered from 1 to n.

    The order of the cell is the number of different values it may contain. Usually, values of a cell of order m are considered to be integer numbers from 0 to m − 1.

    One of the most fundamental properties of a cellular automaton is the type of grid on which it is computed. In this problem we examine the special kind of cellular automaton — circular cellular automaton of order n with cells of order m. We will denote such kind of cellular automaton as n,m-automaton.

    A distance between cells i and j in n,m-automaton is defined as min(|i − j|, n − |i − j|). A d-environment of a cell is the set of cells at a distance not greater than d.

    On each d-step values of all cells are simultaneously replaced by new values. The new value of cell i after d-step is computed as a sum of values of cells belonging to the d-enviroment of the cell i modulo m.

    The following picture shows 1-step of the 5,3-automaton.

    The problem is to calculate the state of the n,m-automaton after k d-steps.

    Input

    The first line of the input file contains four integer numbers nmd, and k (1 ≤ n ≤ 500, 1 ≤ m ≤ 1 000 000, 0 ≤ d < n2 , 1 ≤ k ≤ 10 000 000). The second line contains n integer numbers from 0 to m − 1 — initial values of the automaton’s cells.

    Output

    Output the values of the n,m-automaton’s cells after k d-steps.

    Sample Input

    sample input #1
    5 3 1 1
    1 2 2 1 2
    
    sample input #2
    5 3 1 10
    1 2 2 1 2

    Sample Output

    sample output #1
    2 2 2 2 1
    
    sample output #2
    2 0 0 2 2

    Source

    17861637   3150 Accepted 408K 3579MS G++ 1036B 2017-11-19 20:48:11

    元宝自动机。

    经典的矩阵快速计算方法。

    将有规律的矩阵简化为向量,由原来的 n^3 复杂度减小到 n^2 。

    首先来看一下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矩阵
    b = 1 2 2 1 2
    a =
    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 * a = 5 5 5 5 4
    所以最终结果就是:a * (b^k)

    复杂度是n^3logk,过不了

    于是我们发现这个矩阵长得很奇葩,每一行都是上一行后移一位得到

    所以我们每个矩阵可以变成一行

    参考: https://www.cnblogs.com/iwtwiioi/p/3946211.html

    // poj-3150 
    
    #include <cstdio> 
    #include <cstring> 
    const int MAXN = 500 + 10; 
    
    long long n, m, d, k, num[MAXN], a[MAXN], b[MAXN], tmp[MAXN], ans[MAXN]; 
    
    void MultiPle(long long *aa, long long *bb, long long *cc, int len){ 
    	for(int i=0; i<len; ++i){
    		tmp[i] = 0; 
    		for(int j=0; j<len; ++j){
    			if(i - j >= 0){
    				tmp[i] += (aa[j] * bb[i - j]) % m;  
    			}else{
    				tmp[i] += (aa[j] * bb[i - j + n]) % m; 
    			}
    			tmp[i] %= m; 
    		}
    	}
    	for(int i=0; i<len; ++i){
    		cc[i] = tmp[i]; 
    	}
    }
    
    int main(){
    	freopen("in.txt", "r", stdin); 
    
    	while(scanf("%lld %lld %lld %lld", &n, &m, &d, &k) != EOF){
    		for(int i=0; i<n; ++i){
    			scanf("%lld", &num[i]); 
    		}
    		memset(a, 0, sizeof(a)); 
    		memset(b, 0, sizeof(b)); 
    
    		for(int i=0; i<=d; ++i){
    			a[i] = 1; 
    		}
    		for(int i=n-1; i>n-1-d; --i){
    			a[i] = 1; 
    		}
    		b[0] = 1; 
    
    		while(k){
    			if(k % 2 == 1){
    				MultiPle(b, a, b, n); 
    			}
    			k /= 2; 
    			MultiPle(a, a, a, n); 
    		}
    		MultiPle(num, b, ans, n ); 
    
    		for(int i=0; i<n-1; ++i){
    			printf("%lld ",  ans[i]);
    		}
    		printf("%lld
    ", ans[n-1] );
    	}
    	return 0; 
    }
    

      

  • 相关阅读:
    C# 酒鬼买酒喝,瓶盖和空瓶子可以换新的酒
    C# 图结构操作
    C# 二叉堆
    Unity 单元测试(NUnit,UnityTestTools)
    Unity PlayerPrefs类进行扩展(整个对象进行保存)
    客户端操作判断以服务器时间为准
    C# 使用枚举获取对应的数组值时
    C# 实现简单状态机(参考代码)
    叶脉图案以及藤蔓生长算法在houdini里面的实现 Leaf Venation
    steering behaviors 转向行为 集群模拟 小结
  • 原文地址:https://www.cnblogs.com/zhang-yd/p/7861829.html
Copyright © 2011-2022 走看看