闪烁
闪烁
农夫约翰对牛棚里昏暗的灯光感到不满,刚刚安装了一个新吊灯。
新吊灯由 个灯泡组成,这 个灯泡围成一圈,编号为 。
奶牛对这个新吊灯非常着迷,并且喜欢玩以下游戏:
对于第 个灯泡,如果在 时刻,它左侧的灯泡(当 时,为第 个灯泡;当 时,为第 个灯泡)是开着,那么在 时刻,就切换这个灯泡的状态。
这个游戏将持续 单位时间。
给定灯泡的初始状态,请确定在 单位时间后,它们的最终状态。
输入格式
第一行包含两个整数 和 。
接下来 行,按顺序描述每个灯泡的初始状态,每行包含一个整数 (表示开)或 (表示关)。
输出格式
共 行,按顺序每行输出一个灯泡的最终状态。
数据范围
,
输入样例:
5 6 1 0 0 0 0
输出样例:
1 1 1 0 1
样例解释
灯泡状态如下:
时刻 T=0: 1 0 0 0 0 时刻 T=1: 1 1 0 0 0 时刻 T=2: 1 0 1 0 0 时刻 T=3: 1 1 1 1 0 时刻 T=4: 1 0 0 0 1 时刻 T=5: 0 1 0 0 1 时刻 T=6: 1 1 1 0 1
解题思路
可以发现,每个时刻灯泡亮暗状态的改变可以用二进制的位异或来表示,比如有第个时刻时,第个灯的状态为,则下一个时刻的状态可以表示为。
一共最多有个灯泡,那么最多有种不同的状态,而变化的次数最多有,因此这个状态的转移必然存在一个环。
可以用抽屉原理来证明,假设有个灯泡,如果要变次,而最多只有种不同的状态,因此必然有两种状态是相同的,即必然在进行状态变化的时候会出现循环,即上图中的环。每个状态变化后的新状态是唯一的,对应上图就是每个结点都有唯一一个后继,因此必然存在某个点开始会出现环。
因此我们在枚举状态的时候可以判断一下这个状态之前是否出现过,如果出现过那么表示我们找到一个环,此时我们用原来要循环的次数对这个环的大小取余数得到,然后再从这个出现过点转移次状态就可以得到最终的状态,这个状态与原本要循环的结果是一样的。
我们一开始模拟状态的转移最多需要的计算量,余数最大也是,因此总的计算量最多为。
其中状态的转移是用位运算来实现的,例如:
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 const int N = 1 << 16; 7 8 int mp[N]; 9 10 int main() { 11 int n; 12 LL m; 13 scanf("%d %lld", &n, &m); 14 15 int st = 0; 16 for (int i = 0; i < n; i++) { 17 int x; 18 scanf("%d", &x); 19 st |= x << i; 20 } 21 22 memset(mp, -1, sizeof(mp)); // -1表示这个状态没有出现过 23 mp[st] = 0; // 初始状态为0 24 for (int i = 1; i < 1 << n && i <= m; i++) { // 最多枚举2^n个状态或m次 25 st ^= ((st << 1) | (st >> n - 1 & 1)) & ((1 << n) - 1); // 从当前状态转移到下一个状态 26 // 后面的&((1 << n) - 1)表示将第n位开始往后的位都变成0,这些位都进行&0操作,前面0~n-1为进行&1操作 27 if (mp[st] != -1) { // 这个状态之前出现过,表明出现环 28 int cnt = i - mp[st]; // 计算环的大小 29 int r = (m - i) % cnt; // 此时必然有m >= i,计算在环中要走的步数,即转移的次数 30 while (r--) { // 转移r次 31 st ^= ((st << 1) | (st >> n - 1 & 1)) & ((1 << n) - 1); 32 } 33 34 for (int i = 0; i < n; i++) { 35 printf("%d\n", st >> i & 1); 36 } 37 return 0; 38 } 39 mp[st] = i; // 当前状态是第i个状态 40 } 41 42 // 执行到这里表明i == m + 1,当前的st就是第m个状态 43 for (int i = 0; i < n; i++) { 44 printf("%d\n", st >> i & 1); 45 } 46 47 return 0; 48 }
参考资料
AcWing 1960. 闪烁(寒假每日一题2022):https://www.acwing.com/video/3666/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16358901.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效