回 帖 发 新 帖 刷新版面

主题:第50次编程比赛

一个好汉三个帮,三个好汉九个帮,九个好汉二十七个帮,...停,今天不是让你算n个好汉几个帮(有兴趣的网友可以自己算),我们来看这个集合

{ 1, 3, 9, 27, 81, ... }

这个集合是一个递增的无限集,每个元素都是3的幂。

我们把这个集合的所有子集按照元素和从小到大的顺序排好: {}(空集), { 1 }, { 3 }, { 1, 3 }, { 9 }, { 1, 9 }, { 3, 9 }, { 1, 3, 9 }, ...

现在给定一个正整数n,求第n个子集的所有元素,并按从大到小的顺序排列好

例:

n的值    结果
1        { }
4        { 3, 1 }
6        { 9, 1 }
500      { 6561, 2187, 729, 243, 81, 3, 1 }    

细节要求:
1. n的范围: n >= 1 ,unsigned int
2. 接口:    void HeroNeedThree(INT64* subset, unsigned int n);
   其中INT64是指64位整数,可以用 typedef long long INT64; 也可以自定义
   subset就是存放结果的数组,其中subset[0]存放结果子集的元素个数,
   然后子集元素从大到小存入subset[1],subset[2],......
3. 提供一个简单的测试例程,供大家测试结果是否正确

#include <stdio.h>
#include <stdlib.h>

#define MAX     ( 50  )        //子集结果数组最大容量
#define N       ( 1e8 )       //要测试的N
typedef long long INT64;

void HeroNeedThree(INT64* subset, unsigned int n);

int main(int argc, char *argv[])
{
        INT64 subset[MAX] = {0};
        int i;

        HeroNeedThree(subset, N);

        printf("\n{ ");
        for (i = 1; i <= subset[0]; ++i)
        {
                printf("%I64d, ", subset[i]);
        }
        printf("}\n");

        system("pause");
        return 0;
}

截止到周日3月11日晚。
第一次出题,考虑不周的地方请多多包含。有什么问题请发短信给我。

回复列表 (共47个回复)

沙发

test

板凳

最近实习, 没空做题了。 还是顶一下帖子, 精神上支持一下。

n的值    n-1对应的2进制   对应的集合
1          00000          {  ,  ,  ,  ,  }
2          00001          {  ,  ,  ,  , 1}
4          00011          {  ,  ,  , 3, 1}
11         01010          {  ,27,  , 3,  }
16         11111          {81 27, 9, 3, 1}
  
    呵呵, 规律容易看出来,只要把n转换成二进制, 再计算3的幂就可以。 证明过程略。
    n < 2 ^ 32 - 1, 集合内最大的数是3^32, 不超过64bit,放心大胆的算就可以了。

3 楼

void HeroNeedThree(INT64* subset, unsigned int n)
{
    INT64 num[MAX],*p=num,n1=1;
    for(n--;n>0;n>>=1,n1+=n1<<1)if(n&1)*p++=n1;
    for(*subset=p-num;p!=num;)*++subset=*--p;
}

4 楼

unsigned bit_count(unsigned int n, unsigned &c)
{
    c = 0;
    for(int i=0; i<sizeof(unsigned)*8; i++)
    {
        c += (n >> i) & 0x00000001;
        if(n < (1<<i)) return i;
    }
    return sizeof(unsigned)*8;
}

void HeroNeedThree(INT64* subset, unsigned int n)
{
    unsigned c, t = bit_count(--n, c), s = 1;
    subset[0] = c;
    for(int i=0; i<t; i++)
    {
        if((n&(1<<i))!=0) subset[c--] = s;
#define nexttriexp(prev) ((prev)<<1)+(prev) // next = prev*3
        s = nexttriexp(s);
    }
}

5 楼


[em13]想看一下隐藏的贴.

6 楼


/*题目不错   呼呼   就是我一直没写代码  脑子不清晰 代码编得有点乱:)

再加上要准备一个月后的2+2  所以没多少时间 匆匆写了个 也没来得及注释

主要算法是递归 用到了些类似解决背包问题的方法 。。。

还有就是我电脑上的VC6貌似没有INT64 所以还是改成int了*/

#include <iostream>
using namespace std;

int method(int result[],int *xiabiao,int count[],int data[],int n)
{
    int i=0;
    int j=0;
    
    
    while(count[i]<n)
    {
        i++;
        j++;
    }
    if(n!=count[i])
    {  //如果不能正好减完则返回到前一地址
        j--;
    }
    n-=count[j];
    result[*xiabiao] = data[i];
    *xiabiao+=1;

    if(0==n)
    {
        return count[j];//函数返回当前被减的集合个数
    }
    return method(result,xiabiao,count,data,n);
}

int way(int x)
{  //  返回x个数是的集合总数 2^x
    int i=0;
    int sum=1;
    while(i++<x)
    {
        sum*=2;
    }
    return sum;
}

void HeroNeedThree(int *subset,int n)
{
    int i=1;
    int l1=1;
    int sum(0);
    int data[100]={0};  //存放3的各个幂值
    int count[100]={0}; //存放相应集合总个数
    int *x = new int;
    *x = 1;

    if(1==n)
    {//如果n为1则直接返回结果(空集)
        subset[0] = 0;
        subset[1] = '\0';
        return;
    }

    data[0]=0;
    count[0]=1;
    while(sum+1<=n)
    {
        sum = way(l1);
        count[l1] = sum;
        data[l1] = i;
        i*=3;
        l1++;
    }
    int bb=method(subset,x,count,data,n);
    if(bb!=2)
    {//收尾处理
        if(1==bb)
        {
            subset[*x-1] = '\0';
            *x-=1;
        }
        else
        {
            for(int aa=1;bb!=count[aa+1];aa++);
            for(;aa>=1;aa--)
            {
                subset[*x] = data[aa];
                *x+=1;
            }
            subset[*x] = '\0';
        }
        
    }
    subset[0] = *x-1;//一共保存的个数赋给subset首地址
}

main()
{
    int subset[10] = {0};
    HeroNeedThree(subset,500);
    for(int i=0;i<7;i++)
    {
        cout<<subset[i]<<" ";
    }
}

7 楼

void HeroNeedThree(INT64* subset, unsigned int n)
{
    int i, nCount = 0;
    n --;
    if (0 == n)
        return;
    for (i = 0; i < 4096; i ++)
    {
        if (pow(2, i) > n)
            break;
    }
    if (4096 <= i && i < 0)
        return;
    if (i > 0)
    {
        subset[nCount] = (INT64)pow(3, i-1);
        nCount ++;
        HeroNeedThree(subset, n - (unsigned int)pow(2, i - 1) + 1);
    }
}

8 楼

第一回参加不知道你们对输入输出是怎样规定的=,=
按自己的方式写了一个


#include <stdio.h>
//Viusal C++ 6.0
#define BIGINT __int64
#define FORMAT "%I64d"
/*
mingw use this macro
#define BIGINT long long
#define FORMAT "%I64d"

linux use this macro
#define BIGINT long long
#define FORMAT "%lld"
*/

BIGINT ThreePower[32];

void HeroNeedThree(BIGINT* subset, BIGINT n)
{
    int t, p;
    BIGINT m;
    m = n-1;
    for (t = 0; m; m&=m-1) t++;
    p = 0; m = n-1; subset[0] = t;
    while (t)
    {
        if (m & 1) subset[t--] = ThreePower[p];
        p++;
        m >>= 1;
    }
}

int main()
{
    int i;
    BIGINT n, subset[33];
    ThreePower[0] = 1;
    for (i = 1; i < 32; i++) ThreePower[i] = ThreePower[i-1]*3;
    while (EOF != scanf(FORMAT, &n))
    {
        HeroNeedThree(subset, n);

        printf("{ ");
        for (i = 1; i < subset[0]; i++) printf(FORMAT", ", subset[i]);
        if (subset[0]) printf(FORMAT" ", subset[subset[0]]);
        puts("}");
    }
    return 0;
}

9 楼

//It take a couple of seconds to display

#include <stdio.h>
#include <stdlib.h>

#define MAX     ( 50  )        //×&Oacute;&frac14;&macr;&frac12;á&sup1;&ucirc;&Ecirc;&yacute;×é×&icirc;&acute;ó&Egrave;&Yacute;&Aacute;&iquest;
//Because the speed is too slow, therefore reduce to 1e4
#define N       ( 1e4 )       //&Ograve;&ordf;&sup2;&acirc;&Ecirc;&Ocirc;&micro;&Auml;N ***

#ifndef NULL
#define NULL        0
#endif

typedef long INT64; //My Version of VC doesn't support typedef long long something,
                    //Therefore I just use long.

struct single
{
    INT64* subset;
    struct single *pNext;
};

typedef struct single SINGLE;

//Global

SINGLE* pHead;

//Declare function prototype
void InitSubSet();

void ExpandSubSet(subset,n,StartNumber);

void AppendSingle(SINGLE *pHead,SINGLE* pAppendSingle);

void AppendSingleToHeadNew(SINGLE** ppHeadNew,SINGLE* pAppendSingle);

SINGLE* FindSingle(SINGLE *pHead,unsigned int n);

void FreeSingle(SINGLE* pHead);

void HeroNeedThree(INT64* subset, unsigned int n);

void InitSubSet()
{
    pHead=(SINGLE*)malloc(sizeof(SINGLE));

    pHead->subset=(INT64*)malloc(sizeof(INT64));

    pHead->subset[0]=0;

    pHead->pNext=NULL;
}

void ExpandSubSet(INT64 *subset,unsigned int n,INT64 StartNumber)
{
    static unsigned int nCount=1;
    SINGLE *pNext,*pHeadNew;

    pHeadNew=NULL;

    if(nCount>=n)
    {
        SINGLE *pLastSingle;
        int i;

        pLastSingle=FindSingle(pHead,n);

        for(i=0;i<=pLastSingle->subset[0];i++)
            subset[i]=pLastSingle->subset[i];

        FreeSingle(pHead);

        return;
    }
    //snapshot
    pNext=pHead;
    while(pNext!=NULL)
    {
        int i,nFactor;
        INT64 *pI64;
        SINGLE *pSingle;

        nFactor=pNext->subset[0];    
        pI64=(INT64*)malloc(sizeof(INT64)*(nFactor+1+1));
        pSingle=(SINGLE*)malloc(sizeof(SINGLE));

        for(i=0;i<=nFactor;i++)        //Copy old Data and add current one
        {
            pI64[i]=pNext->subset[i];
        }
        (*pI64)++;
        *(pI64+*pI64)=StartNumber;

        pSingle->subset=pI64;
        pSingle->pNext=NULL;
        
        AppendSingleToHeadNew(&pHeadNew,pSingle);

        nCount++; // We append one item to the table
        pNext=pNext->pNext;
    } //End of While
    AppendSingle(pHead,pHeadNew);

    ExpandSubSet(subset,n,StartNumber*3);
        
}

void AppendSingle(SINGLE *pHead,SINGLE* pAppendSingle)
{
    SINGLE* pNext;

    if(pHead==NULL)
    {

        pHead=pAppendSingle;
        return;
    }

    pNext=pHead;


    while(pNext->pNext!=NULL)
        pNext=pNext->pNext;

    pNext->pNext=pAppendSingle;
}

void AppendSingleToHeadNew(SINGLE** ppHeadNew,SINGLE* pAppendSingle)
{
    SINGLE *pNext;

    if(*ppHeadNew==NULL)
    {
        *ppHeadNew=pAppendSingle;
        return;
    }
    else
    {
        pNext=*ppHeadNew;
        while(pNext->pNext!=NULL)
        {
            pNext=pNext->pNext;
        }
        pNext->pNext=pAppendSingle;
    }
}

SINGLE* FindSingle(SINGLE *pHead,unsigned int n)
{
    SINGLE *pNext;
    unsigned int i;

    pNext=pHead;

    for(i=1;i<n;i++)
    {
        pNext=pNext->pNext;
    }

    return pNext;
}

void FreeSingle(SINGLE* pHead)
{
    SINGLE *pNext;
    SINGLE *pSave;

    pNext=pHead;

    while(pNext->pNext!=NULL)
    {
        pSave=pNext->pNext;

        free(pNext);

        pNext=pSave;
    }

    free(pNext);
    pHead=NULL;

}

void HeroNeedThree(INT64* subset, unsigned int n)
{
    InitSubSet();
    if(n==1)
    {
        *subset=0;
        return;
    }
    ExpandSubSet(subset,n,1); //
}

int main(int argc, char *argv[])
{
        INT64 subset[MAX] = {0};
        int i;

        HeroNeedThree(subset, N);

        printf("\n{ ");
        for (i = 1; i <= subset[0]; ++i)
        {
                printf("%d, ", subset[i]);// I change &I64 to %d as well.
        }
        printf("}\n");

        system("pause");
        return 0;
}

10 楼

void    HeroNeedThree(INT64*    subset, unsigned int n)
{
    int    c=0,m,i=1;
    int flag=0;
    while(1)
    {    
        m=n;
        c=log2(n);
        n=1<<c;
        n=m-n;
        switch(n)
        {
        case 0 : 
            {
                while(c)
                {
                    subset[i++]=(long)pow(3,(c-1));             
                    c--;
                }
                flag=1;
                break;
            }
        case 1:    
            {
                subset[i++]=(long)pow(3,c);
                flag=1;
                break;
            }
        default : subset[i++]=(long)pow(3,c);
     
        }
        if(flag)
            break;
    }    
    subset[0]=i-1;
}

我来回复

您尚未登录,请登录后再回复。点此登录或注册