现在我有26个元素a...z
我想自由生成相关的组合
从一位起
a
a+b
a+b+c
a+b+c+d
......
生成所有组合对顺序没有要求,即a+b 和 b+a可以当同一条,不用重复出现

解决方案 »

  1.   

    http://blog.sina.com.cn/s/blog_589d32f5010007wv.html
      

  2.   


    program Project4;{$APPTYPE CONSOLE}uses
      SysUtils;var
      myArr : array [0..25] of AnsiString = ('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z');
    var
       i , j : integer;
       s : AnsiString;
    begin
      try
        for i := 0 to {2的26次方} do
        begin
          s := '';
          for j := 0 to 25 do
          begin
            if (i and (1 shl j) <> 0 )  then
            begin
              s :=  s + myArr[j] + '+';
            end ;      end;
          writeln(s);
        end;
    {这里把 字符串最后一个 + 要去掉,我就不去掉了}
        Readln(s);  except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
    end.
      

  3.   

    这倒没有那么夸张,楼的需求,只是一个“26选1” + "26选2" + ... + "26选26",总共是67108863个,如果每一个字符占用一个字节的话,不计算任何其他的因结构等需要的分隔符,总共是872415232字节,即832MB,如果使用StringList的话,需要使用内存2GB。
      

  4.   

    这个2GB怎么来的呢,你可以这样子计算,首先StringList需要有一个Item的动态数组,共需要67108863个,这个数组的类型是TStringItem类型的指针,每个占用4字节。同时需要67108863个TStringItem对象实例,每个占用8字节,而TStringItem实际存储数据的是一个String类型,String类型除了数据外,其中有引用计数和长度各点4字节,另外还需要一个结束符#0。在所有String全部按实际须用进行分配计算的话是2.176GB。
      

  5.   

    不就一个回溯算法吗?要知道我可是NOIP的
      

  6.   


    program Project1;{$APPTYPE CONSOLE}var
      a:array [0..26] of char;
      s:set of char;
      j:integer;procedure print(n:integer);//打印过程
    var
      i:integer;
    begin
      for i:=1 to n-1 do write(a[i],'+');
      writeln(a[n]);
    end;procedure Search(num:Integer;t:integer);//回溯过程
    var
      ch:char;
    begin
      if t>num then
      begin
        print(num);
        exit;
      end;
      for ch:=a[t-1] to 'z' do
        if ch in s then
        begin
          s:=s-[ch];
          a[t]:=ch;
          search(num,t+1);
          s:=s+[ch];
        end;
    end;begin
      assign(output,'output.out');rewrite(output);
      //初始化数据
      a[0]:='a';
      s:=['a'..'z'];
      for j:=1 to 26 do search(j,1);//主过程,j越大会越久,因为是递归调用
      close(output);
    end.
      

  7.   

    天。。文件打不开。。太大了
    只能用WinHex或UltraEdit打开。。但无法计算行数
      

  8.   

    怎么存的,为什么会有这么大?
    结果的总字节数应该:872415232,加上67108863(或67108862)个回车换行计134217726(或134217724),总计应该是1006632958(1006632956),0.9375GB,即便使用Unicode,约为1.875GB,也不会是1.7G
      

  9.   

    这类问题,直接用位不就搞定了?才26位,不足一个正整数的大小,不过这方法结果不是
    A,AB,ABC这样的顺序,而是A,B,AB,AC
    var
      aLineBuffer : Array [0..26-1 + 2] of AnsiChar;
      hFile : THandle;
      sBuf : AnsiString;
      iBufSize : integer;
      iBufUseSize : integer;
    //返回位数,字符串保存于aLineBuffer中,返回位数中包含回车换行符
    Function  IndexToBuffer(Index : DWORD) : integer;
    asm
          XOR     ECX , ECX
          LEA     EDX , aLineBuffer
    @@Loop:
          BTR     EAX , ECX
          JNC     @@Next
          MOV     [EDX] , CL
          ADD     [EDX] , 'A'
          INC     EDX
    @@Next:
          TEST    EAX , EAX
          JZ      @@Break
          INC     ECX
          CMP     ECX , 26
          JNZ     @@Loop
    @@Break:
          MOV     [EDX].WORD , $0A0D
          LEA     EAX , aLineBuffer
          SUB     EDX , EAX
          LEA     EAX , [EDX+2]
    end;//初始化文件
    Function InitSaveFile(Const FileName : AnsiString) : Boolean;
    begin
      hFile := CreateFile(PAnsiChar(FileName),GENERIC_READ or GENERIC_WRITE,
                          FILE_SHARE_READ or FILE_SHARE_WRITE,
                          nil, CREATE_ALWAYS,
                          FILE_ATTRIBUTE_NORMAL , 0);
      Result := hFile<>INVALID_HANDLE_VALUE;
    end;//写入缓冲区到硬盘
    procedure SaveToFile;
    var
      D : DWORD;
    begin
      WriteFile(hFile , Pointer(sBuf)^ ,  iBufUseSize , D , NIL);
      iBufUseSize := 0;
    end;//把当前行增加到缓冲区中
    procedure AppendToBuf(LineSize : integer);
    begin
      if LineSize+iBufUseSize>iBufSize then SaveToFile;
      Move(aLineBuffer , Ptr(Integer(sBuf) + iBufUseSize)^ , LineSize);
      iBufUseSize := iBufUseSize + LineSize;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      Index , n , nCount , nTime : DWORD;
    begin
      if not InitSaveFile('E:\dd.dat') then exit;  iBufSize := 20 * 1024 * 1024;     //缓冲区 20M
      iBufUseSize := 0;
      SetLength(sBuf , iBufSize);  nTime := GetTickCount();
      nCount := 0;
      Index := 1;
      while True do begin
        n := IndexToBuffer(Index);
        Inc(nCount , n);
        AppendToBuf(n);
        if n=28 then Break;
        Inc(Index);
      end;
      nTime := GetTickCount() - nTime;
      Caption := '总字节数:' + IntToStr(nCount) + '  耗时:' + IntToStr(nTime) + '豪秒';
      if iBufUseSize<>0 then SaveToFile;
      SetLength(sBuf , 0);
      CloseHandle(hFile);
    end;总共60秒,不写盘20秒,不写缓冲区13秒,可见瓶颈,如果用IOCP写文件估计会好一点 1.6的烂CPU
    文件大小 1006632958 Bytes 吻合 僵哥的计算
      

  10.   

    高手!!
    不过没加加号,加了也就我那个答案。
    我是从算法的角度去分析。。
    还有,文件操作可用Assign(),不然有点麻烦。。
      

  11.   

    BTR Dest , SourDest的第Sour位 送CF ,并把这个位置0
      

  12.   

    更新一下Bug,才想到的Function  IndexToBuffer(Index : DWORD) : integer;
    asm
          XOR     ECX , ECX
          LEA     EDX , aLineBuffer
    @@Loop:
          BTR     EAX , ECX
          JNC     @@Next
          MOV     [EDX] , CL
          ADD     [EDX].Byte , 'A'
          INC     EDX
          TEST    EAX , EAX
          JZ      @@Break
    @@Next:
          INC     ECX
          CMP     ECX , 26
          JNZ     @@Loop
    @@Break:
          MOV     [EDX].WORD , $0A0D
          LEA     EAX , aLineBuffer
          SUB     EDX , EAX
          LEA     EAX , [EDX+2]
    end;
      

  13.   

    又组合公式  C(n,m)=A(n,m)/m!=n!/((n-m)!*m!)
    可知你的结果数量为 ∑n!/((n-m)!*m!) n=26 m=1...26
    共 67108863 个具体到每一个的值,建议你先看一下“高效的10移动算法”,无递归
      

  14.   

    {$define LINE_BREAK} //要不要换行符自己选//要不要分隔符,自己决定
    //{$define NEED_SPLIT_CHAR}{$ifdef NEED_SPLIT_CHAR}
      {$define LINE_BREAK} //分隔符都要了,换行符你就别省了
    {$endif}{$ifdef LINE_BREAK}
      //{$define LINE_BREAK_UNIX_LIKE} //类Unix的标准当中只有换行0x0a,没有回车0x0d
    {$endif}
    function DataToText(  OffSet: DWORD       (*缓冲区偏移*)
                        ; Data: DWORD         (*当前值*)
                        ; Buffer : PAnsichar  (*缓冲区基址*)
                        ):DWORD;
    asm
      //保护他人的劳动成果人人有责
      push ebx@@LOOP:
      BSF EBX, EDX    //从右至左取首个有效比特位(即bit=1),结果存入EBX (取值:0..31)
      JZ  @@RET       //如果整个EDX都没有一个big=1,则ZF标志被设置,别犹豫了,结束吧
      BTR EDX, EBX    //取走么,自然是真的拿走的啦
      ADD EBX, 'A'    //转成字母,才更方便查看嘛
    {$ifdef NEED_SPLIT_CHAR}
      MOV BH, '+'     //有人说需要中间的分隔符呢,这个么...不是问题,你想要就给你加上,反正我不要
      Mov WORD PTR [ECX + EAX], BX //没啥好说,写到缓冲区保存成果,要不然没有会知道的
      ADD EAX, 2      //写了两个字节,自然就要报告两个字节,这个时候不需要谦虚
    {$else}
      Mov Byte PTR [ECX + EAX], BL //报告,这是组合当中的其中一个元素
      Inc EAX         //写了一个字节
    {$endif}
      jmp @@LOOP      //还没结束呢,继续吧
    @@RET:
    {$ifdef NEED_SPLIT_CHAR}
      //占用最后一个'+'的位置
      {$ifdef LINE_BREAK}
        {$ifdef LINE_BREAK_UNIX_LIKE}
          MOV Byte PTR [ECX + EAX - 1], $0a
        {$else}
          MOV Word PTR [ECX + EAX - 1], $0a0d
          Inc EAX
        {$endif}
      {$else}
        Dec EAX  //吃多了吧,赶紧吐出来
      {$endif}
    {$else}
      {$ifdef LINE_BREAK}
      {$ifdef LINE_BREAK_UNIX_LIKE}
        MOV Byte PTR [ECX + EAX], $0a
        Inc EAX
      {$else}
        MOV Word PTR [ECX + EAX], $0a0d
        ADD EAX, 2
      {$endif}
      {$endif}
    {$endif}  //归还他人的劳动成果也是我们应尽的义务
      pop ebx
    end;
    procedure TForm1.Button1Click(Sender: TObject);
    var
      I:DWORD;
      i64Start, i64End, i64Freq : Int64;
      D: array of AnsiChar;
      L: DWORD;
      M, N, E, T: DWORD;
    begin
      M := 26;                     //这个不用解释(M <= 32)
      L := 1024;      //预置缓冲区大小(写文件的话,请自行调整)  QueryPerformanceFrequency(i64Freq);  QueryPerformanceCounter(i64Start); //计时开始  E := $FFFFFFFF shr (32 - M);  //计算个数   //实际缓冲区大小,比预置多分配 (M字节 + (M - 1)个"+" + 0x0a0d回车换行) (这里面只是应大众的使用习惯)
      SetLength(D, L + M + (M - 1) + 2);  T := 0; //字节数统计  N := 0; //单批写入字节数
      for I := 1 to E do begin
        N := DataToText(N, I, @D[0]);
        if N >=  L then begin      //缓冲写满,请进行保存N个字节
          //...      T := T + N; //这里只做统计
          N := 0; //重头开始写入
        end;
      end;
      //如果N > 0,请进行保存N个字节
      //...
      T := T + N; //这里只做统计  QueryPerformanceCounter(i64End); //计时结束  ShowMessage('总字节数:' + IntToStr(T) +'  耗时:' + IntToStr((i64End - i64Start)(*秒*) * 1000 (*毫秒*) * 1000 (*微秒*) div i64Freq (*时钟频率*)) + '微秒');end;
      

  15.   

    全部生成的组合要存储,用MYSQL存,约40亿个组合
      

  16.   

    说得对呀我就是要这样的效果,“26选1” + "26选2" + ... + "26选26"这样的出来的组合所有结果存起来,没想到多少MB都给unsigned计算出来了,高人
      

  17.   

    HSFZXJY
    你真的用你贴出的算法计了一次吗。的确利害!1。7G真的想不到这么大
      

  18.   

    在我的固态硬盘上写入文件在10秒以内,在机械硬盘(光驱位托架支撑,60MB/S)为20秒,一般的配机械硬盘的机器应该在15秒以内
    program Project1;{$APPTYPE CONSOLE}uses
      SysUtils,
      windows;
    function GetOverlappedResult(hFile: THandle; const lpOverlapped: POverlapped;
      var lpNumberOfBytesTransferred: DWORD; bWait: BOOL): BOOL; stdcall; external kernel32;
    {$define LINE_BREAK} //要不要换行符自己选//要不要分隔符,自己决定
    {$define NEED_SPLIT_CHAR}{$ifdef NEED_SPLIT_CHAR}
      {$define LINE_BREAK} //分隔符都要了,换行符你就别省了
    {$endif}{$ifdef LINE_BREAK}
      //{$define LINE_BREAK_UNIX_LIKE} //类Unix的标准当中只有换行0x0a,没有回车0x0d
    {$endif}
    function DataToText(  OffSet: Cardinal       (*缓冲区偏移*)
                        ; Data: Cardinal         (*当前值*)
                        ; Buffer : PAnsichar  (*缓冲区基址*)
                        ):Cardinal;
    asm
      //保护他人的劳动成果人人有责
      push ebx@@LOOP:
      BSF EBX, EDX    //从右至左取首个有效比特位(即bit=1),结果存入EBX (取值:0..31)
      JZ  @@RET       //如果整个EDX都没有一个bit=1,则ZF标志被设置,别犹豫了,结束吧
      BTR EDX, EBX    //取走么,自然是真的拿走的啦
      ADD EBX, 'A'    //转成字母,才更方便查看嘛
    {$ifdef NEED_SPLIT_CHAR}
      MOV BH, '+'     //有人说需要中间的分隔符呢,这个么...不是问题,你想要就给你加上,反正我不要
      Mov WORD PTR [ECX + EAX], BX //没啥好说,写到缓冲区保存成果,要不然没有会知道的
      ADD EAX, 2      //写了两个字节,自然就要报告两个字节,这个时候不需要谦虚
    {$else}
      Mov Byte PTR [ECX + EAX], BL //报告,这是组合当中的其中一个元素
      Inc EAX         //写了一个字节
    {$endif}
      jmp @@LOOP      //还没结束呢,继续吧
    @@RET:
    {$ifdef NEED_SPLIT_CHAR}
      //占用最后一个'+'的位置
      {$ifdef LINE_BREAK}
        {$ifdef LINE_BREAK_UNIX_LIKE}
          MOV Byte PTR [ECX + EAX - 1], $0a
        {$else}
          MOV Word PTR [ECX + EAX - 1], $0a0d
          Inc EAX
        {$endif}
      {$else}
        Dec EAX  //吃多了吧,赶紧吐出来
      {$endif}
    {$else}
      {$ifdef LINE_BREAK}
      {$ifdef LINE_BREAK_UNIX_LIKE}
        MOV Byte PTR [ECX + EAX], $0a
        Inc EAX
      {$else}
        MOV Word PTR [ECX + EAX], $0a0d
        ADD EAX, 2
      {$endif}
      {$endif}
    {$endif}  //归还他人的劳动成果也是我们应尽的义务
      pop ebx
    end;var
      I:cardinal;
      i64Start, i64End, i64Freq : Int64;
      D: array of AnsiChar;
      L: cardinal;
      M, N, E, T: cardinal;  OutputFile: THandle;
      ovl:OVERLAPPED ;
      Size: Cardinal;begin
      try
        { TODO -oUser -cConsole Main : Insert code here }
        M := 26;            //这个不用解释(M <= 32)
        L := 512*1024;      //预置缓冲区大小(写文件的话,请自行调整)    QueryPerformanceFrequency(i64Freq);    QueryPerformanceCounter(i64Start); //计时开始    //创建文件
        OutputFile:= CreateFile(  'G:\Test.dat',
                                  GENERIC_READ or GENERIC_WRITE,
                                  FILE_SHARE_READ,
                                  nil,
                                  CREATE_ALWAYS,
                                  FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED, (*Overlapped为重叠IO支持,异步写入*)
                                  0);
        //常规写法应当要判断OutputFile的值是否为Invalid_Handle_value,即创建文件是否失败
        //...    fillchar(ovl,  sizeof(ovl), 0); //初始化重叠结构
        ovl.hEvent := CreateEvent(NIL,true,true,Nil);  //异步IO事件通知模式    E := $FFFFFFFF shr (32 - M);  //计算个数     //实际缓冲区大小,比预置多分配 (M字节 + (M - 1)个"+" + 0x0a0d回车换行) (这里面只是应大众的使用习惯)
        SetLength(D, L + M + (M - 1) + 2);    T := 0; //字节数统计    N := 0; //单批写入字节数
        for I := 1 to E do begin
          N := DataToText(N, I, @D[0]);
          if N >=  L then begin        //缓冲写满,请进行保存N个字节
            WriteFile( OutputFile,D[0],N,Size,@ovl); //异步提交一次写操作,正规写法应当判断返回值
            WaitForSingleObject(ovl.hEvent,INFINITE); //等待完成事件
            GetOverlappedResult( OutputFile, @ovl, Size, true);  //取异步操作结果,实际写入字节数
            ovl.Offset := ovl.Offset + Size;                     //设置下一次写入的起始文件偏移
            SetFilePointer(OutputFile, Size, NIL, FILE_CURRENT); //设置文件偏移        T := T + N; //这里只做统计
            N := 0; //重头开始写入
          end;
        end;
        //如果N > 0,请进行保存N个字节
        WriteFile( OutputFile,D[0],N,Size,@ovl);
        WaitForSingleObject(ovl.hEvent,INFINITE);
        GetOverlappedResult( OutputFile, @ovl, Size, true);
        SetFilePointer(OutputFile, Size, NIL, FILE_CURRENT);
        SetEndOfFile(OutputFile);  //设置文件结尾
        closeHandle(ovl.hEvent);   //关闭事件句柄
        CloseHandle(OutputFile);   //关闭文件句柄,释放文件操作权
        T := T + N; //这里只做统计    QueryPerformanceCounter(i64End); //计时结束    writeln('总个数:'+IntToStr(E)+'  总字节数:' + IntToStr(T) +'  耗时:' + IntToStr((i64End - i64Start)(*秒*) * 1000 (*毫秒*) * 1000 (*微秒*) div i64Freq (*时钟频率*)) + '微秒');  except
        on E:Exception do
          Writeln(E.Classname, ': ', E.Message);
      end;
    end.
      

  19.   

    To kiboisme(蓝色光芒):
      在你的汇编代码当中,需要注意保护被你使用的常规寄存器,
    例如"Function  IndexToBuffer(Index : DWORD) : integer;"这个函数当中,只是告诉了编译器你会占用EAX,而实际当中你却使用了ECX和EDX,当启用了编译器的优化功能之后,这个函数就非常危险,因为被无故地修改了ECX和EDX寄存器的内容,就会造成不可预知的后果。而这种代码往往是在调试状态(DEBUG版本)当中所有一切都正常,便是当发布了release版本到客户现场之后,莫名其妙的问题就来了,死循环,内存写异常,程序崩溃无不皆有可能。
      

  20.   


    [code]生成所有组合对顺序没有要求,即a+b 和 b+a可以当同一条,不用重复出现[/code]
      

  21.   

    生成所有组合对顺序没有要求,即a+b 和 b+a可以当同一条,不用重复出现
      

  22.   

    To unsigned (僵哥(自然界因不公平生生不息))
      BSF有效减少了循环,直接把Buffer的当前位置传进去当作当前写的地址,避免了Move,大大提高的效率,真棒。  至于ECX,EDX未保护的情况,确实存在问题,不严禁,应该带上在函数定义处,带上assembler关键字即可避免这类情况。
      

  23.   

    To unsigned (僵哥(自然界因不公平生生不息))
      

  24.   

    assembler关键字确实可以解决寄存器冲突问题,但是却有可能打破编译器自身的优化效果。往往我们会认为自己用汇编写的代码非常有针对目的性,应该可以有相当的性能提升。但是若被应用到一个非瓶颈热点的例程当中去,就可能会因为我们编码时未考虑到的一些问题,而达不到预期的性能效用且影响了编译器本应当起到的优化效果。
      

  25.   

    嗯,a+b 和 b+a可以当同一条,不用重复出现
      

  26.   

    (C26 1 + C26 2 +........+C26 13)*2
      

  27.   

    一共不就是26+25+...+1,即351种组合。
    a
    ab
    abc
    ...
    abc...Zb
    bc
    bcd
    ...
    bcd...z依次类推算法很简单这样理解对吗?
      

  28.   

    程序可能有BUG或错误的地方,欢迎各路好友切磋!!
    写硬盘程序运行时间:30秒 (普通机械硬盘)
    不写硬盘运行时间:4秒 (仅写入输出缓存)
    输出文件大小:895 MB (939,524,095 bytes)(含“,”分隔符)
    int _tmain(int argc, _TCHAR* argv[])
    {
    HANDLE hFile = INVALID_HANDLE_VALUE;
    char timebuf[20] = {0};

    DWORD TimeStart;
    DWORD TimeEnd;
    DWORD TimeUsed; system("pause");
    TimeStart = GetTickCount(); hFile = CreateFileA( "./output.txt",
    GENERIC_WRITE|GENERIC_READ,
    FILE_SHARE_READ,
    NULL,
    CREATE_ALWAYS,
    FILE_ATTRIBUTE_NORMAL,
    NULL); if (INVALID_HANDLE_VALUE == hFile)
    return FALSE; for (DWORD i=1; i<67108864; i++)
    PrintStr(i, hFile);

    CloseHandle(hFile); TimeEnd = GetTickCount();
    TimeUsed = TimeEnd - TimeStart;
    printf("67108863 records, time costs: %ld(ms)\n", TimeUsed);
    system("pause"); return 0;
    }void PrintStr(DWORD n, HANDLE hFile)
    {
    /* 26 bits for a ~ z: |  8bits | 8bits  | 8bits  | 8bits  |
    |------00|00000000|00000000|00000000|
    |    zy|xwvutsrq|ponmlkji|hgfedcba| a ~ z: 97 ~ 122 */ static char buf[28*1024*1024] = {0}; //28mb
    static int datalen = 0; DWORD temp = 1;
    char ch = 'a'; for (int i=0; i<26; i++)
    {
    if (n & temp)
    buf[datalen++] = ch; ch++;
    temp = temp << 1;
    } buf[datalen++] = ','; if ((datalen > (28*1024*1024 - 28)) || 67108863 == n)
    {
    DWORD wtlen = 0;
    WriteFile(hFile, buf, datalen, &wtlen, 0);
    memset(buf, 0, sizeof(buf));
    datalen = 0;
    }
    }
      

  29.   

    程序可能存在bug,欢迎各位好友切磋
    运行时间:30秒 (写入硬盘文件) 文件大小:895 MB (939,524,095 bytes)含“,”分隔符
    运行时间:4秒  (不写硬盘只写入输出缓存)
    void PrintStr(DWORD n, HANDLE hFile);int _tmain(int argc, _TCHAR* argv[])
    {
    HANDLE hFile = INVALID_HANDLE_VALUE;
    char timebuf[20] = {0};

    DWORD TimeStart;
    DWORD TimeEnd;
    DWORD TimeUsed; system("pause");
    TimeStart = GetTickCount(); hFile = CreateFileA( "./output.txt",
    GENERIC_WRITE|GENERIC_READ,
    FILE_SHARE_READ,
    NULL,
    CREATE_ALWAYS,
    FILE_ATTRIBUTE_NORMAL,
    NULL); if (INVALID_HANDLE_VALUE == hFile)
    return FALSE; for (DWORD i=1; i<67108864; i++)
    PrintStr(i, hFile);

    CloseHandle(hFile); TimeEnd = GetTickCount();
    TimeUsed = TimeEnd - TimeStart;
    printf("67108863 records, time costs: %ld(ms)\n", TimeUsed);
    system("pause"); return 0;
    }void PrintStr(DWORD n, HANDLE hFile)
    {
    /* 26 bits for a ~ z: |  8bits | 8bits  | 8bits  | 8bits  |
    |------00|00000000|00000000|00000000|
    |    zy|xwvutsrq|ponmlkji|hgfedcba| a ~ z: 97 ~ 122 */ static char buf[28*1024*1024] = {0}; //28mb
    static int datalen = 0; DWORD temp = 1;
    char ch = 'a'; for (int i=0; i<26; i++)
    {
    if (n & temp)
    buf[datalen++] = ch; ch++;
    temp = temp << 1;
    } buf[datalen++] = ','; if ((datalen > (28*1024*1024 - 28)) || 67108863 == n)
    {
    DWORD wtlen = 0;
    WriteFile(hFile, buf, datalen, &wtlen, 0);
    memset(buf, 0, sizeof(buf));
    datalen = 0;
    }
    }
      

  30.   

    程序可能存在bug,欢迎各位好友切磋
    运行时间:30秒 (写入硬盘文件) 文件大小:895 MB (939,524,095 bytes)含“,”分隔符
    运行时间:4秒  (不写硬盘只写入输出缓存)
    void PrintStr(DWORD n, HANDLE hFile);int _tmain(int argc, _TCHAR* argv[])
    {
    HANDLE hFile = INVALID_HANDLE_VALUE;
    char timebuf[20] = {0};

    DWORD TimeStart;
    DWORD TimeEnd;
    DWORD TimeUsed; system("pause");
    TimeStart = GetTickCount(); hFile = CreateFileA( "./output.txt",
    GENERIC_WRITE|GENERIC_READ,
    FILE_SHARE_READ,
    NULL,
    CREATE_ALWAYS,
    FILE_ATTRIBUTE_NORMAL,
    NULL); if (INVALID_HANDLE_VALUE == hFile)
    return FALSE; for (DWORD i=1; i<67108864; i++)
    PrintStr(i, hFile);

    CloseHandle(hFile); TimeEnd = GetTickCount();
    TimeUsed = TimeEnd - TimeStart;
    printf("67108863 records, time costs: %ld(ms)\n", TimeUsed);
    system("pause"); return 0;
    }void PrintStr(DWORD n, HANDLE hFile)
    {
    /* 26 bits for a ~ z: |  8bits | 8bits  | 8bits  | 8bits  |
    |------00|00000000|00000000|00000000|
    |    zy|xwvutsrq|ponmlkji|hgfedcba| a ~ z: 97 ~ 122 */ static char buf[28*1024*1024] = {0}; //28mb
    static int datalen = 0; DWORD temp = 1;
    char ch = 'a'; for (int i=0; i<26; i++)
    {
    if (n & temp)
    buf[datalen++] = ch; ch++;
    temp = temp << 1;
    } buf[datalen++] = ','; if ((datalen > (28*1024*1024 - 28)) || 67108863 == n)
    {
    DWORD wtlen = 0;
    WriteFile(hFile, buf, datalen, &wtlen, 0);
    memset(buf, 0, sizeof(buf));
    datalen = 0;
    }
    }
      

  31.   

    不重复的组合,abc、acb、bac、bca、cab、cba都是一样的,算一种
      

  32.   

    无顺序不重复的组合 abc、acb、bac、bca...都算一种组合
      

  33.   

    居然用起了回溯,不知道直接用数学解决吗,算法不是用来让问题变复杂的。
    规模为1时,有两种组合:null, a
    规模为2时,在原有组合基础上增加b: b, a+b
    再加上原有组合,所有排列为(null,a,b,a+b)
    规模为3时,在原有组合上增加c: c, a+c, b+c, a+b+c
    再加上原有组合,所有排列为 (null,a,b,a+b,c,a+c,b+c,a+b+c)
    ...
    这个问题实际上是一个等比数列,设f(1)=2, f(n)=2*f(n-1),如果不计算空,最后结果减1即可,通项为2^n-1。
    按照上述步骤一次性遍历所有结果,无任何多余操作,我就不信还有人能找出比这个更快的算法。
      

  34.   


       if (n & temp)
         buf[datalen++] = ch;
       ...
         //代码在这里用得比较巧妙...
      

  35.   

    思路:
          二进制-->逆序-->找出值为1的位对应的字母
          1-->1-->A        10-->01-->B     11-->11-->AB
         100-->001-->C    101-->101-->AC   110-->011-->BC
         111-->111-->ABCJAVA实现:
    public class Thr{
    public static void main(String[] args) {
    System.out.println("总计" + ((1 << 26)-1)+"种组合");
    char[] ch = {'A','B','C','D','E','F','G',
         'H','I','J','K','L','M','N','O','P',
         'Q','R','S','T','U','V','W','X','Y','Z'};
    int n = (1<<ch.length)-1;
    int i = 0;
    StringBuffer sb = new StringBuffer();
    while(i++ < n){
    String revBinStr = sb.append(Integer.toBinaryString(i))
    .reverse().toString();//逆序二进制字符串
    create(ch,revBinStr);
    sb.delete(0,revBinStr.length());
    System.out.println();//换行
    }
    }


           //找出值为1的位的下标,输出ch中对应该下标的
    public static void create(char[] ch,String revBinStr ){
    int currentIndex = 0;
    for(int x = 0; x < ch.length; ){
    currentIndex = revBinStr.indexOf("1",x);
    if(currentIndex != -1 ){
    System.out.print(ch[currentIndex]);
    x = currentIndex + 1;
    }else{
    break;
    }
    }
    }
    }