【解题报告】洛谷P5657 格雷码

【解题报告】洛谷P5657 格雷码

题目链接

https://www.luogu.com.cn/problem/P5657

思路

我们大眼观察数据

然后发现, \(n\) 位格雷码实际上是由 \(n-1\) 位格雷码转化而来

找规律知道,除去第一位之外,前一半和后一半的数值实际上是中心对称的,所以我们打出了如下的暴力

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
using namespace std;
unsigned long long n,k;
void dfs(unsigned long long n,unsigned long long k)
{
	if(n==0)
	return ;
	long long x=(1<<(n-1));//表示有多少个
	if(k==0)//如果k为0的话,没有好吧
	{
		for(long long i=1;i<=n;i++)
		cout<<"0";
		return ;
	}
	if(k+1>x)//如果要的数字在中间的右边
	{
		long long next=2*x-k-1;//计算对应右边的n-1位格雷码
		cout<<"1";
		dfs(n-1,next);
	}
	else//在左边就是正常的格雷码
	{
		long long next=k;
		cout<<"0";
		dfs(n-1,next);
	}
}
int main()
{
	//freopen("code.in","r",stdin);
	//freopen("code.out","w",stdout);
	cin>>n>>k;
	dfs(n,k);
	cout<<endl;
//	fclose(stdin);
 //	fclose(stdout); 
	return 0;
}

这份代码可以得到60pts的高分

所以我们继续研究

分别把自己能手算出来的每个格雷码和 \(k\) 进行对比发现

\(k\ge 2\) 的时候,第 \(k\) 个格雷码的第 \(1\) 位是 \(k-2\) 的第二位去翻的结果,否则格雷码的第一位是 \(0\)

实际上还有更方便的方法

考虑答案的每一位,发现格雷码第 \(i\) 位是 \(k \space xor \space \lfloor \dfrac k 2 \rfloor\) 的第 \(i\)

然后。。。就过了?

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
int n;
unsigned long long k;
int main()
{
	cin>>n>>k;
	k^=k>>1;
	while(~--n)
	cout<<(k>>n&1);
	return 0;
}
posted @ 2021-10-11 19:45  wweiyi  阅读(106)  评论(0编辑  收藏  举报
js脚本