【解题报告】洛谷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;
}
本博文为wweiyi原创,若想转载请联系作者,qq:2844938982