微软2014实习生在线测试题:K-th String

原题是有N个0和M个1组成序列(2 <= N + M <= 33 and N , M >= 0),按字典序排列,求出第K个串,若K超出则输出Impossible;

其实就是全排列,并从小到大的顺序排列,求第K个。

首先判断K是否超出,计算N个0和M个1组成全排列有total= 种,若K>a则超出。
total个全排列中,前a= 种是第一位为0,即第一位为0,其余M+N-1位是N-1个0和M个1组成全排列,所以判断a和K的关系就可以断定第一位是0还是1,若a>=K,则第一位是0;若a<K,则第一位是1,则求N个0和M-1个1组成全排列中的第K-a个串。依此循环。。。。

代码:
#include<iostream>
#include<string>
using namespace std;
int getTotalNumber(int n,int m)//C M(M+N)
{
    int all=n+m;
    int total=1;
    for(int i=all;i>n;i--)
        total*=i;
    for(int j=m;j>1;j--)
        total=total/j;
    return total;

}

int main()
{
    //cout<<getTotalNumber(-1,3)<<","<<getTotalNumber(3,1)<<endl;

    int caseNum;
    cin>>caseNum;
    int n,m,k;
    for(int c=0;c<caseNum;c++)
    {
        cin>>n>>m>>k;
        if(getTotalNumber(n,m)<k||k<=0)
        {
            cout<<"Impossible"<<endl;
            continue;
        }
        while(n>=1||m>=1)
        {
            int a=getTotalNumber(n-1,m);
            if(a>=k)
            {
                cout<<"0";
                n--;               
            }
            else
            {
                cout<<"1";
                m--;
                k=k-a;
            }
        }
        cout<<endl;       
    }
    return 0;
}


提交后提示Wrong Answer,但得50分,当时怎么也没想通哪些测试用例会出错。

今天做leetcode上的Unique Paths,意思是从m*n的格子的坐上顶端走到右下底端所有的路径数,组合数学里学的,总共要走m-1次的向下一步和n-1次的向右一步,也就是从m+n-2次总选出m-1次的向下一步,共有 种。   把上面的getTotalNumber函数copy一下再改改 提交,发现(10,10)时出错,int越界?  把 total改成 long long型,再linux 上用g++编译(VC 6.0不支持long long),(10,10)的输出结果正确了,再提交,(23,12)错误,我的程序输出的是0,再加个m和n比大小,让m成为较小者,进一步降低total的值,再提交,通过!

由此,K-th String的问题也清楚了,是因为int越界,使得较大的N和M测试用例测试失败,
修改
int getTotalNumber(int n,int m)//C M(M+N)
{
    if(m>n)
    {
        int tmp=m;
        m=n;
        n=tmp;
    }
    int all=n+m;
    long long total=1;
    for(int i=all;i>n;i--)
        total*=i;
    for(int j=m;j>1;j--)
        total=total/j;
    return total;
}
应该可以通过了!

转自我的搜狐博客 http://jluhlh.blog.sohu.com/302327975.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值