2019D1T1 格雷码

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

在这张表格里,我发现了这些规律:

  1. (nleq 4)时,数据都是本表格的一部分,如:(n=2)时是前(2 imes 2^2)格,(n=3)时是前(2 imes 2^3)
  2. (n)每增加1,相当于把表格前三列向下翻转,然后在最后一列前半部分添加1,后半部分添加0,具体过程如下
    表格变换

(这是我一开始找到的规律,打算开始模拟,然鹅我发现)

  1. (来了来了)对于寻找序列里第(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

  2. 就在我这样写完之后,试了一组小样例发现不对!因为什么呢?因为当第一位是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;
}
要做就做南波万
原文地址:https://www.cnblogs.com/liuziwen0224/p/2019d1t1.html