(AC)并不是很难,但考试太紧张只拿了(95pts)
我的省选之路就从这开始吧
(Description)
题面
格雷码是一种编码,(n)位格雷码构造方式如下:
将(n-1)位格雷码加前导("0")作为(0--2^{n-1}-1)位,再将(n-1)位格雷码倒序,加前导("1")作为(2^{n-1}--2^n-1)位
特别的,(1)位格雷码为(0,1)
问(n)位格雷码的第(k)个是什么
(Solution)
考虑写出格雷码形成了一个树形结构,找出格雷码的过程就类似数据结构查询第(k)位,由于(k)是从(0)开始的,所以先把他(+1)
假设当前考虑到第(i)位,则令(mid=2^{i-1}),假如(k<=mid)则补(0),否则(k-=mid),补(1),注意(1)下面的排序是倒序的,所以把排名翻转(:k=mid-k+1)
注意几点:
(1.)要开(ull),在(ull)下(x<<63)这种运算是错的,自己写快速幂
(2.)极端数据(k=2^{64}-1)如果(k++)会爆(ull)变成(0),由于(k)在我们的程序中永远也不会变成(0),所以遇到(k=0),反转后就是(k=1),直接特判即可。
(Code)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#define re register
#define ull unsigned long long
using namespace std;
inline ull read()
{
ull x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
string s;
ull n,k,mid;
ull quickpow(ull a,ull b)
{
ull ans=1;
while(b)
{
if(b&1) ans=ans*a;
a=a*a;
b>>=1;
}
return ans;
}
int main()
{
n=read(),k=read();
mid=quickpow(2,n-1);
k++;
while(mid)
{
if(k>mid||k==0)
{
s+='1';
if(!k) k=1;
else k-=mid,k=mid-k+1;
}
else s+='0';
mid>>=1;
}
cout<<s;
return 0;
}