poj 3150 Cellular Automaton

本文探讨了一个细胞自动机的问题,其中每个状态在一定距离内的状态变化通过矩阵快速幂实现优化。通过理解循环矩阵的性质,我们简化了矩阵乘法过程,并通过实例演示了如何高效计算操作后的状态分布。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        题意:一个细胞自动机(名字真高级)包含n个格子,每个格子的值为0~m-1。给定距离d,每次操作后每个格子的值将变为到它的距离不超过d的所有格子在操作之前的和模m。。求操作k次后每个格子的值。

        思路:在白书上看了题目,马上敲了一份矩阵快速幂代码,发现在matrix结构体里面开500*500的数组的话,程序根本运行不起来,因为局部变量占用了过多的内存。然后看了下白书的思路,居然有一个结论,用于变换的矩阵肯定是形如

1 1 0 0 1

1 1 1 0 0

0 1 1 1 0

0 0 1 1 1

1 1 0 0 1

的,像这样每行循环右移的矩阵称为循环矩阵。循环矩阵的积还是循环矩阵。。因此,只需要计算矩阵的第一行就可以了。

        发几个需要注意的地方:

1.矩阵元素相乘会溢出int。

2.在取模前一定要确保那个数不是负数。

3.一定要仔细推演原矩阵i行j列的元素等于第一行的哪一个。


#include <iostream>           
#include <stdio.h>           
#include <cmath>           
#include <algorithm>           
#include <iomanip>           
#include <cstdlib>           
#include <string>           
#include <string.h>           
#include <vector>           
#include <queue>           
#include <stack>           
#include <map>         
#include <assert.h>
#include <set>         
#include <ctype.h>                
#define ll long long       
#define max3(a,b,c) max(a,max(b,c))       

using namespace std;       

int n,m,d,k;

struct mat{
	ll v[1][512];
	mat(){
		memset(v,0,sizeof(v));
	}
};

mat mat_mul(mat a,mat b,int siz){
	mat re;
	for(int i=0;i<1;i++){
		for(int j=0;j<siz;j++){
			for(int k=0;k<siz;k++){
				re.v[i][j]+=a.v[i][k]*b.v[i][(siz+j-k)%siz];
				re.v[i][j]%=m;
			}
		}
	}
	return re;
}

mat mat_pow(mat m,int n,int siz){
	mat re;
	mat tmp=m;
	re.v[0][0]=1;
	while(n){
		if(n&1){
			re=mat_mul(re,tmp,siz);
		}
		tmp=mat_mul(tmp,tmp,siz);
		n>>=1;
	}
	return re;
}

		
int main(){
	while(cin>>n>>m>>d>>k){
		
		ll vec[512];
		for(int i=0;i<n;i++){
			cin>>vec[i];
		}
		
		mat a;
		for(int j=0;j<=d;j++){
			a.v[0][(j)%n]=1;
			a.v[0][(n-j)%n]=1;
		}		

		mat ak=mat_pow(a,k,n);
		
		for(int i=0;i<n;i++){
			if(i)cout<<" ";
			ll ans=0;
			for(int j=0;j<n;j++){
				ans+=ak.v[0][(j+n-i)%n]*vec[j];
				ans%=m;
			}
			cout<<ans;
		}
		cout<<endl;
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值