首页 > 其他分享 >[题解]细胞自动机

[题解]细胞自动机

时间:2024-07-06 22:20:52浏览次数:23  
标签:le Matrix int 题解 细胞 bmatrix 自动机 log

给定一个长度为\(n\)的\(01\)串\(s\),用于表示一个环上的细胞的初始状态,其中第\(1\)个细胞与第\(2\)个、第\(n\)个细胞相邻;第\(n\)个细胞与第\(1\)个和第\(n-1\)个相邻。\(0\)表示细胞死亡,\(1\)表示细胞存活。接下来给定\(t\)轮操作,每一轮操作,根据上一轮细胞的状态更改此轮的状态。规则如下:

  • 如果上一轮中与该细胞相邻的\(2\)个细胞中正好有\(1\)个存活,那么此轮中该细胞存活。否则此轮中该细胞死亡。

给定正整数\(t\),请输出一个\(01\)串,表示\(t\)轮变化后每个细胞的存活状态。

数据范围:对于\(50\%\)的数据,保证\(3\le n\le 15\),\(1\le T\le 10^{15}\)。
对于所有数据,保证\(3\le n\le 10^5\),\(1\le T\le 10^{15}\)

样例:

Sample #1

Input

7 1
0000001

Output

1000010
Sample #2

Input

5 3
01011

Output

10100

50pts - 矩阵快速幂解法 - \(O(n^3\log t)\)

考虑用广义矩阵乘法代替普通矩阵乘法:把两数相乘改为两数取与,两数相加改为两数去异或。

则可以构建初始矩阵和递推矩阵(拿\(6\)阶举例,其他同理):

\[A=\begin{bmatrix} 输入的01串\dots \end{bmatrix}, B=\begin{bmatrix} 0&1&0&0&0&1\\ 1&0&1&0&0&0\\ 0&1&0&1&0&0\\ 0&0&1&0&1&0\\ 0&0&0&1&0&1\\ 1&0&0&0&1&0 \end{bmatrix}\]

点击查看代码
#include<bits/stdc++.h>
#define N 510
#define int long long
using namespace std;
int n,t;
string s;
struct Matrix{
	int n,m;
	bool a[N][N];
	Matrix(int na,int ma){n=na,m=ma,memset(a,0,sizeof a);}
	bool* operator [](int x){return a[x];}
	Matrix(){memset(a,0,sizeof a);}
	Matrix operator*(const Matrix &b) const{
		Matrix res(n,b.m);
		for(int i=1;i<=n;i++){
			for(int j=1;j<=b.m;j++){
				for(int k=1;k<=m;k++){
					res[i][j]^=a[i][k]&b.a[k][j];
				}
			}
		}
		return res;
	}
}a,base;
void qpow(int b){
	while(b){
		if(b&1) a=a*base;
		base=base*base;
		b>>=1;
	}
}
signed main(){
	cin>>n>>t>>s;
	a.n=1,a.m=base.n=base.m=n;
	for(int i=1;i<=n;i++) a[1][i]=s[i-1]-'0';
	for(int i=1;i<=n;i++){
		int p1=i-1,p2=i+1;
		if(p1==0) p1+=n;
		if(p2==n+1) p2-=n;
		base[i][p1]=base[i][p2]=1;
	}
	qpow(t);
	for(int i=1;i<=n;i++) cout<<a[1][i];
	return 0;
}

但由于此方法复杂度是\(O(n^3\log T)\),空间是\(O(n^2)\),都无法承受。

100pts - 找规律&倍增 - \(O(n\log T)\)

假设现在有一个无限长的环:
...000000010000000...
进行变化(下面用#表示\(1\),空格表示\(0\)),发现:

                         #    //初始状态
                        # #    //经过1次变化
                       #   #    //经过2次变化
                      # # # #
                     #       #    //经过4次变化
                    # #     # #
                   #   #   #   #
                  # # # # # # # #
                 #               #    //经过8次变化
                # #             # #
               #   #           #   #
              # # # #         # # # #
             #       #       #       #
            # #     # #     # #     # #
           #   #   #   #   #   #   #   #
          # # # # # # # # # # # # # # # #
         #                               #    //经过16次变化
        # #                             # #
       #   #                           #   #
      # # # #                         # # # #
     #       #                       #       #
    # #     # #                     # #     # #
   #   #   #   #                   #   #   #   #
  # # # # # # # #                 # # # # # # # #
 #               #               #               #
# #             # #             # #             # #
                   .............

很神奇地,我们发现这是一个分形图(谢尔宾斯基三角形)。

当然这不是重点,我们发现,经过\(2^k\)次变化后,只有一开始的活细胞左边第\(2^k\)个细胞和右边第\(2^k\)个细胞是活的,其他全是死的。

因此我们可以得知任意一种环上,变化\(2^k\)次后每个活细胞向左右的贡献,即:对于每个活细胞,将其左&右边第\(2^k\)个细胞状态取反,自己也取反。

通过把\(t\)二进制分解,可以转化成若干个\(2^k\)次变化,重复上述操作即可。

时间复杂度\(O(n\log t)\),可以通过。

注意是一个环,所以位置需要取模\(n\)。

#include<bits/stdc++.h>
#define N 100010
#define int long long
using namespace std;
int n,t,a[2][N];
string s;
int modn(int a){return ((a%n)+n)%n;}
signed main(){
	cin>>n>>t>>s;
	bool cur=0;
	for(int i=0;i<n;i++) a[0][i]=s[i]-'0';
	for(int ii=0,w=1;ii<55;ii++,w<<=1){//k=2^i
		if(t&w){
			cur^=1;
			for(int i=0;i<n;i++) a[cur][i]=a[cur^1][i];
			for(int i=0;i<n;i++) if(a[cur^1][i]) a[cur][i]^=1,a[cur][modn(i-w)]^=1,a[cur][modn(i+w)]^=1;
		}
	}
	for(int i=0;i<n;i++) cout<<a[cur][i];
	return 0;
}

标签:le,Matrix,int,题解,细胞,bmatrix,自动机,log
From: https://www.cnblogs.com/Sinktank/p/18285664

相关文章

  • P9668 [ICPC2022 Jinan R] Torch 题解
    思路考虑使用矩阵模拟这个过程。首先,我们可以设初值为:\[\begin{bmatrix}0&1\end{bmatrix}\]表示瘦子初始走\(0\)米,胖子初始走\(1\)米。考虑瘦子走一步。由于瘦子每走一步都不能超过胖子,我们可以使用\((\min,+)\)矩乘来维护这个性质。那么瘦子走一步是:\[\begin{bma......
  • CF292C Beautiful IP Addresses 题解(两种写法)
    题意一个IP地址是一个32位的2进制整数,分成四组8位的2进制整数(没有前导0)。比如说,0.255.1.123 是一个正确的IP地址,而0.256.1.123 和 0.255.1.01 不是正确的。定义一个合法的回文IP地址为BeautifulIPAddress(回文地址就是去掉“.”后是个回文字符串的地......
  • 沪越联赛 - 2024年6月月赛Div2 题解
    问题A:替换题目描述小明每次注释的时候都写\(n\)个/。小红看了小明的程序,觉得太难看了,那么多/,所以决定把这些没用的/都去掉。小红定义了一个宏命令,每次可以将所有连续的\(m\)个/替换成空(注意不是空格)小明得知了小红的企图后非常着急,因为他知道光把/都去掉,那么原......
  • C++题解(3) 信息学奥赛一本通: 1013:温度表达转化 洛谷:B2013 温度表达转化 土豆编程:M
    【题目描述】利用公式 C=5×(F−32)÷9C=5×(F−32)÷9(其中CC表示摄氏温度,FF表示华氏温度)进行计算转化,输入华氏温度FF,输出摄氏温度CC,要求精确到小数点后55位。【输入】输入一行,包含一个实数FF,表示华氏温度。(F≥−459.67)(F≥−459.67)【输出】输出一行,包含一个......
  • [AGC064D] Red and Blue Chips 题解
    题目链接点击打开链接题目解法挺牛的题这种计数本质不同的结果的题,一个很不错的切入口是判断结果的合法性令B的总数为\(m\)我们把结果串先挂在第\(m\)个B上考虑从后往前枚举原串(最后一个B不枚举),相当于我们在倒序模拟操作过程枚举到B,我们相当于要把后面的一个B......
  • HT-014 Div3 扫雷 题解 [ 绿 ] [ 二维差分 ]
    分析观察到是曼哈顿距离\(\ler\)的范围可以扫到,联想到如下图形:左边是\(r=1\)可以扫到的范围,右边是\(r=2\)可以扫到的范围。于是,我们只要对这样的图形在\(1000*1000\)的格子里差分一下就好了。但这样的复杂度是\(O(nm)\)的,会死的很惨。优化不难发现这个图形是一......
  • HT-014 Div3 跳棋 题解 [ 黄 ] [ 并查集 ] [ 树型结构 ]
    分析依旧是一个连通块题。观察题面不难发现两个重要性质:一个跳棋只能以它旁边的两个跳棋为中点跳跃,且满足跳跃路线中除中点以外没有其它跳棋阻挡。只有我们的跳棋可以移动。跳棋的操作具有可逆性/对称性。第三条性质可以这么理解,就是一个跳棋跳过去之后,它还可以跳回来。......
  • [POI2015] WYC 题解
    [POI2015]WYC显然矩阵乘法发现点数和边权非常小,所以可以考虑拆点把每个点拆为\(u_1\),\(u_2\),\(u_3\),初始:\(u_1\tou_2\),\(u_2\tou_3\),每一条加边:\(u+(w-1)\timesn\tov\)因为\(k\)非常大,所以考虑倍增优化注意:答案会爆longlong,需要使用unsignedlonglong//Pro......
  • python-docx库 写入docx时中文不适配问题,中文异常问题解决办法。
    python-docx库写入docx时中文不适配问题,中文异常问题解决办法。通过以下方法可以成功将正文修改为宋体字体。这个是全文设置。fromdocx.oxml.nsimportqndoc=Document()doc.styles['Normal'].font.name=u'宋体'doc.styles['Normal']._element.rPr.rFonts.set(qn('w:......
  • ZeroMQ最全面试题解读(3万字长文)
    目录解释ZeroMQ是什么,它的主要用途是什么?ZeroMQ支持哪些通信模式?描述一下ZeroMQ中的“消息”和“消息帧”如何在C++中初始化一个ZeroMQ上下文?在ZeroMQ中,如何创建一个套接字并将其绑定到特定端口?解释什么是“管道模式”(PipePattern)说明如何使用ZeroMQ进行点对点通信Zer......