ACM ICPC 2011–2012, Northeastern European Regional Contest Problem B. Binary Encoding

这里写图片描述
这里写图片描述
题意:对于一个数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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值