2019D1T1 格雷码
DTQT D1T1 题解
咕咕咕的Day1过去了
我的做法
通过手动计算,我画出了(n=4)时候的这张表格:
(请注意:本表格倒序存放)
第4位 | 第3位 | 第2位 | 第1位 |
---|---|---|---|
0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 |
1 | 1 | 0 | 0 |
0 | 1 | 0 | 0 |
0 | 1 | 1 | 0 |
1 | 1 | 1 | 0 |
1 | 0 | 1 | 0 |
0 | 0 | 1 | 0 |
0 | 0 | 1 | 1 |
1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 |
0 | 1 | 1 | 1 |
0 | 1 | 0 | 1 |
1 | 1 | 0 | 1 |
1 | 0 | 0 | 1 |
0 | 0 | 0 | 1 |
在这张表格里,我发现了这些规律:
- (nleq 4)时,数据都是本表格的一部分,如:(n=2)时是前(2 imes 2^2)格,(n=3)时是前(2 imes 2^3)格
- (n)每增加1,相当于把表格前三列向下翻转,然后在最后一列前半部分添加1,后半部分添加0,具体过程如下
(这是我一开始找到的规律,打算开始模拟,然鹅我发现)
-
(来了来了)对于寻找序列里第(t)个(为了描述方便我们从把编号改为(1-2^n)),定义(l=1,r=2^n),显然(mid=frac{l+r}{2})(按照C++,这里(mid)应该比真实的平均值少0.5,所以会出现最后判断不停止的情况,我的做法是加上0.5,让它一直保持在中间,不知道想的是否全面),加完0.5以后得到的(mid)与(p)比较,如果小于那么所输出数的第一位一定是0,否则是1
-
就在我这样写完之后,试了一组小样例发现不对!因为什么呢?因为当第一位是1时,后面的一组数据会是1在前,0在后,于是有了下面这一段代码:
long long p=k+1;
long long tot=quick_pow(2,n);
long long l=1,r=tot;
int y=n;
bool ishang=1;
while(y--){
double mid=(l+r)/2;
if(p<mid+0.5){
if(y==n) printf("0"),ishang=1;
else if(ishang) printf("0");
else if(!ishang) printf("1"),ishang=1;
r=mid;
}
if(p>mid+0.5){
if(y==n) printf("1"),ishang=0;
else if(!ishang) printf("0");
else if(ishang) printf("1"),ishang=0;
l=mid;
}
}
(自认为)复杂度可以达到(O(n)),虽然咕咕了(莫名自信)
Day2跟着混吧,没什么打算
代码贴上,欢迎质疑
(对了我还是一个骗分的小宝宝)
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
long long k;
int n;
int h[70][50000];
int ansd[70];
int cnt=3;
long long quick_pow(long long a,long long b){
if(b==1){
return a;
}
else if(b%2==0){
b/=2;
return quick_pow(a,b)*quick_pow(a,b);
}
else{
b/=2;
return quick_pow(a,b)*quick_pow(a,b)*a;
}
}
int main(){
// freopen("code.in","r",stdin);
// freopen("code.out","w",stdout);
scanf("%d%lld",&n,&k);
h[1][1]=0,h[2][1]=0,h[3][1]=0;
h[1][2]=1,h[2][2]=0,h[3][2]=0;
h[1][3]=1,h[2][3]=1,h[3][3]=0;
h[1][4]=0,h[2][4]=1,h[3][4]=0;
h[1][5]=0,h[2][5]=1,h[3][5]=1;
h[1][6]=1,h[2][6]=1,h[3][6]=1;
h[1][7]=1,h[2][7]=0,h[3][7]=1;
h[1][8]=0,h[2][8]=0,h[3][8]=1;
if(n==1){
if(k==1)printf("1
");
else printf("0
");
return 0;
}
else if(n==2){
for(int i=n;i>=1;i--){
printf("%d",h[i][k+1]);
}
printf("
");
return 0;
}
else if(n==3){
for(int i=n;i>=1;i--){
printf("%d",h[i][k+1]);
}
printf("
");
return 0;
}
else {
long long p=k+1;
long long tot=quick_pow(2,n);
long long l=1,r=tot;
int y=n;
bool ishang=1;
while(y--){
double mid=(l+r)/2;
if(p<mid+0.5){
if(y==n) printf("0"),ishang=1;
else if(ishang) printf("0");
else if(!ishang) printf("1"),ishang=1;
//printf("0");
r=mid;
}
if(p>mid+0.5){
if(y==n) printf("1"),ishang=0;
else if(!ishang) printf("0");
else if(ishang) printf("1"),ishang=0;
l=mid;
}
}
}
printf("
");
return 0;
}