您的位置:首页 > 其它

高效解决 2.K-th string (微软2014在线笔试,第二题)

2014-04-13 21:15 447 查看
Time Limit: 10000ms

Case Time Limit: 1000ms

Memory Limit: 256MB

Description

Consider a string set that each of them consistsof {0, 1} only. All strings in the set have the same number of 0s and 1s. Writea program to find and output the K-th string according to the dictionary order.If s​uch 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 setwith 6 different strings, {0011, 0101, 0110, 1001, 1010, 1100}, and the 4thstring is 1001.

Input

The first line of the input file contains a singleinteger t (1 ≤ t ≤ 10000), the number of test cases, followed by the input datafor each test case.

Each test case is 3 integers separated by blankspace: 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 asoutput.

Output

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

Sample In

3

2 2 2

2 2 7

4 7 47

Sample Out

0101

Impossible

01010111011
////////////////////////////////////////////

本问题属于排序问题,寻找第K位数

对于已排好序的数组则时间复杂度为O(1)

未排好序的数组,时间复杂度为O(N)(N为数组大小)

本问题如果要得到排序,首先时间复杂度就会很高,为O(C(N,M+N))

思路很简单,就是排列组合的知识。



但是这样做复杂度太高。

采用计数的方式,计算全排列个数,则可以将时间复杂度降到O(M+N),这里假设计算排列组合的时间复杂度为O(1)(事实上,确实可以做到,只是需要使用公式)



循环:



如果减少1个0后的排序个数仍大于K,则可以在首位放一个0,组合数变为C(N-1,M+N-1);



小于K,则首位放置一个1,但是这时应该更新K,因为放置1之后,余下部分的排列数中已经减少了一部分,剩下的排列组合数只需要补足余下的个数就可以了,组合数变为C(N,M+N)。



若等于K,则退出循环,剩余的0和1只需按最大排列即可。即1在前面,0在后面。



具体减少多少呢?

减少量 = 当前组合数 – 取走1之后的组合数

K = K – 减少量



这样循环下去,只需要最多M+N次,能得到该Kth 字符串;



具体边界条件比较简单,参看代码即可。

(代码水平比较渣,凑合看吧,lz正在努力学习中。没有参加微软的笔试,所以只是实现了思路,具体OJ的话,代码应该也比较好改)

附:第一次发博客,转载注明啊~

#include <iostream>
using namespace std;
int Count(int up, int down){
	if (up > down / 2)
		up = down - up;
	long long fenzi = 1;
	long long fenmu = 1;
	for (int i = 1; i <= up; ++i)
		fenmu *= i;
	for (int i = down - up + 1; i <= down; ++i)
		fenzi *= i;
	return fenzi / fenmu;
}

bool getK(int zero, int one, int K, char* res){
	int up = zero;
	int down = zero + one;
	int C = Count(up, down);
	if (C < K) 
		return false;
	int index = 0;
	while (C!=K && up < down && up > 0)
	{
		if (Count(up-1,down-1) >= K) {
			up--;
			down--;
			res[index] = '0';
		}
		else{
			down--;
			K =  K - (C - Count(up,down));
			res[index] = '1';
		}
		C = Count(up, down);
		index++;
	}
	int tmp = index - 1;
	for (; index <= tmp + down - up; ++index)
		res[index] = '1';
	tmp = index - 1;
	for (; index <= tmp + up; ++index)
		res[index] = '0';
	res[index + 1] = '\0';
	return true;
}

int main()
{
	char *res = new char[16];
	if (getK(2, 2, 6, res)) 
		cout << res << endl;
	else
		cout << "Impossible" << endl;
	delete [] res;
	system("pause");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: