zoukankan      html  css  js  c++  java
  • [微软实习生2014]K-th string

    很久之前的事情了,微软2014实习生的在线测试题,记录下来以备后用。

    题目描述:

    Description

    Consider a string set that each of them consists of {0, 1} only. All strings in the set have the same number of 0s and 1s. Write a program to find and output the K-th string according to the dictionary order. If such a string doesn’t exist, or the input is not valid, please output “Impossible”. For example, if we have two ‘0’s and two ‘1’s, we will have a set with 6 different strings, {0011, 0101, 0110, 1001, 1010, 1100}, and the 4th string is 1001.

    Input

    The first line of the input file contains a single integer t (1 ≤ t ≤ 10000), the number of test cases, followed by the input data for each test case.
    Each test case is 3 integers separated by blank space: N, M(2 <= N + M <= 33 and N , M >= 0), K(1 <= K <= 1000000000). N stands for the number of ‘0’s, M stands for the number of ‘1’s, and K stands for the K-th of string in the set that needs to be printed as output.

    Output

    For each case, print exactly one line. If the string exists, please print it, otherwise print “Impossible”.

    样例输入

    3
    2 2 2
    2 2 7
    4 7 47

    样例输出

    0101
    Impossible
    01010111011

    题解:

      这道题目本身不是很难,题目的大概意思是让我们从N个0、M个1组成的二进制数从小到大排列中找出第k个。话虽这么说,但事实上肯定不能这么做,N和M虽然不大(最大到33),但其排列组合的规模依然非常可观,暴力法的时间消耗是不能接受的。

      说说我的想法吧。首先从0、1排列的那些数从小到大的排列中,一个很显然的是第一个数是0的肯定比第一个数是1的要小,而且我们要找的那个第k个数,要么在首位为0的那一拨里,要么在首位为1的那一拨里,也就是说,我们只要比较首位为0的数的个数与k的大小,就知道应该是属于哪一拨!至于怎么计算首位为0的数的个数,这是排列组合的基本知识。首先N个0和M个1组成的所有数的数目为(N+M)!/(N!*M!),那么,固定首位为0,就是求N-1个0和M个1组成的所有数的数目,即(N-1+M)!/((N-1)!*M!)

      有了这个基本的想法,我们接下来只要递归得做这样一件事情就行。以题中的输入2 2 2为例,对于初始情形,2个0和2个1共有6种组合,其中第一位为0的有3个,由k小于3,所以肯定这个数在首位为0的那一拨里,这时就可以输出第一位“0”,如果这里k大于3,那么输出首位为“1”,并在首位为1的那一拨里找第k-3大的,这么递归下去即可。

      代码如下:

     1 #include <iostream>
     2 
     3 using namespace std;
     4 
     5 int jiecheng(int n)
     6 {
     7     if(n==1 || n==0) return 1;
     8     return n*jiecheng(n-1);    
     9 }
    10 
    11 int allNum(int n,int m)
    12 {
    13     return jiecheng(n+m)/(jiecheng(n)*jiecheng(m));
    14 }
    15 
    16 void fun(int n,int m,int k)
    17 {
    18     int znum;
    19     if(k>allNum(n,m)) return;
    20     if(n==0)
    21         znum=0;
    22     else
    23         znum = allNum(n-1,m);
    24     if(m==0 && n==0)
    25         return;
    26     if(m==0 && n!=0)
    27     {
    28         for(int i=0; i<n; i++)
    29             cout<<"0";
    30         return;        
    31     }
    32     if(k>znum)//在以1开头的里面 
    33     {
    34         cout<<"1";
    35         fun(n,m-1,k-znum);         
    36     }
    37     else
    38     {
    39         cout<<"0";
    40         fun(n-1,m,k);
    41     }
    42 }
    43 int main()
    44 {
    45     int T;
    46     int N,M,K;
    47     int total;
    48     cin>>T;
    49     while(T--)
    50     {
    51         cin>>N>>M>>K;
    52         if(N==0 && M==0)
    53         {
    54             cout<<"Impossible"<<endl;
    55             continue;      
    56         }
    57         if(N!=0 && M==0 && K==1)
    58         {
    59             for(int i=0; i<N; i++)
    60                 cout<<"0";
    61             cout<<endl;
    62             continue;      
    63         }
    64         total = allNum(N,M);
    65         if(K>total)
    66         {
    67             cout<<"Impossible"<<endl;
    68             continue;
    69         }
    70         fun(N,M,K);
    71         cout<<endl;
    72     }
    73     return 0;    
    74 }
    View Code

      ps:这个代码比较丑陋,有一个重要的问题是,当N+M很大时,(N+M)!/(N!*M!)会超出int的表示范围,这时候需要用一些其他的高精度类型来表示,这算是本题的一个陷阱,不是核心内容,具体不表。

  • 相关阅读:
    绘图1——图形标记
    polyfit实例1
    polyfit函数-帮助文档
    C# 中泛型与非泛型?(摘)
    C# 数组和集合(摘)
    C#中字符与字符串(转)
    C# 表达式与运算符(转)
    C#中的变量和常量(转)
    C#变量的声明和初始化(转)
    变量的声明、定义、初始化(转)
  • 原文地址:https://www.cnblogs.com/codershell/p/3734384.html
Copyright © 2011-2022 走看看