GYM103743H Super Gray Pony - 思维 -
题目链接:https://codeforces.com/gym/103743/problem/H
这应该是近期做出来的最难的题之一了……想了一个多小时
首先,如何由 求得 ?
考虑 的每一位 0/1
如果第一位是 1,那么相当于就知道了剩下的数字在 (即在右侧)中,此时如果第二位为 0,由于 是反过来的,因此相当于是在 的左侧,即 的右侧,因此对应的格雷码是 1.
找规律可以发现:对于一个 01 串,求格雷码的方法就是,如果出现一个 1,那么 标记为 1,继续接下来,如果是 0 记 1,否则记 0(如果标记为 0 的话就不变了),如果当前记的是 1,那么标记反转,以此类推
我们发现这本质上就是异或,如果 的格雷码是 ,那么根据上面的算法我们就可以得到 ,同理写出 ,两式异或得
考虑多次重复这个过程,考虑 的格雷码 ,那么同理有
因此,我们得到算 阶格雷码的方法:
这里出现了一个问题: 的 项没了,通过打表/数学归纳法可以得到当 是 2 的幂次时,前面的 项是不变的
因此我们可以将 拆成 2 的幂次之和,然后用我们的做法求出 阶格雷码
代码相当好写
#include <bits/stdc++.h>
#define mpr make_pair
typedef long long ll;
using namespace std;
const int inf = 1e9, maxn = 3e6 + 5;
int n,k;
char s[maxn];
int a[maxn];
signed main(){
scanf("%d%d",&n,&k);
scanf("%s",s + 1);
for(int i=1;i<=n;i++)a[i] = s[i] - '0';
for(int i=0;i<=30;i++)
if(k & (1 << i)){
int qw = (1 << i);
for(int j=n;j>=qw+1;j--)
a[j] ^= a[j-qw];
}
for(int i=1;i<=n;i++)
printf("%d",a[i]);
puts("");
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示