题意:对于一个数m,要用不同的01串(类似二进制编码)表示出0到m-1。
串的长度是n或n-1。(n为满足该表达式的最小整数:2^n>=m)
并且长度为n-1的串不可以是长度为n的串的前缀。
分析:算出n,在数组中依次存下所有比特数为(n-1)的串。
如m=6,则n=3,在数组中存的串是:
00
01
10
11
这里只有4个串,而我们需要6个串,剩下的串的长度一定只能是3,然而在此基础上直接加长度为3的串,一定会出现前缀的问题。
因此,我们考虑删掉一个长度为2的串,并在这个串的末尾添0或添1,使其成为一个长度为3的串,加入数组中。
在这里需要删除“10”、“11”两个串。
具体实现:用递归的方法生成序列。另外推荐读者了解一下二进制衍射格雷码,一个很有意思的东西。
附上AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
#define maxn 10005
#define rush() int t;scanf("%d",&t);while(t--)
using namespace std;
int s[10010][15];
void GrayCode(int &x,const int Max,const int N)
{
int tmp = x;
if (x > Max)
return;
for (int i = N - 1; i >= 0; --i)
s[tmp][i]=(x >> i)&1;
GrayCode(++x, Max,N);
}
void TestGray(int cnt)
{
int x = 0;
int n = cnt;
int maxx=pow(2,cnt)-1;
GrayCode(x, maxx, n);
}
int main()
{
freopen("binary.in","r",stdin);
freopen("binary.out","w",stdout);
int m,n=1,cnt=2;
scanf("%d",&m);
if(m==2)
{
printf("0\n1\n");
return 0;
}
while(m>cnt)
{
n++;
cnt*=2;
}
int low_bit=n-1;
TestGray(low_bit);
int ans=pow(2,low_bit);
int ned=m-ans;
int cut=ans-ned;
for(int i=0;i<cut;i++)
{
for(int j=low_bit-1;j>=0;j--)
printf("%d",s[i][j]);
printf("\n");
}
for(int i=cut;i<ans;i++)
{
for(int k=0; k<2; k++)
{
for(int j=low_bit-1; j>=0; j--)
printf("%d",s[i][j]);
if(k==0)
printf("0\n");
else
printf("1\n");
}
}
return 0;
}