CodeForces_1360H Binary Median(数论+暴力)

Binary Median

time limit per test:2 seconds
memory limit per test:256 megabytes
Problem Description

Consider all binary strings of length m m m ( 1 ≤ m ≤ 60 1≤m≤60 1m60). A binary string is a string that consists of the characters 0 and 1 only. For example, 0110 is a binary string, and 012aba is not. Obviously, there are exactly 2 m 2^m 2m such strings in total.

The string s is lexicographically smaller than the string t (both have the same length m) if in the first position i from the left in which they differ, we have s [ i ] < t [ i ] s[i]<t[i] s[i]<t[i]. This is exactly the way strings are compared in dictionaries and in most modern programming languages when comparing them in a standard way. For example, the string 01011 01011 01011 is lexicographically smaller than the string 01100, because the first two characters are the same, and the third character in the first string is less than that in the second.

We remove from this set n n n ( 1 ≤ n ≤ m i n ( 2 m − 1 , 100 ) 1≤n≤min(2^m−1,100) 1nmin(2m1,100)) distinct binary strings a 1 a_1 a1, a 2 a_2 a2,…, a n a_n an, each of length m. Thus, the set will have k = 2 m − n k=2^m−n k=2mn strings. Sort all strings of the resulting set in lexicographical ascending order (as in the dictionary).

We number all the strings after sorting from 0 0 0 to k − 1 k−1 k1. Print the string whose index is ⌊ k − 1 ⌋ 2 \frac{⌊k−1⌋}{2} 2k1 (such an element is called median), where ⌊ x ⌋ ⌊x⌋ x is the rounding of the number down to the nearest integer.

For example, if n = 3 n=3 n=3, m = 3 m=3 m=3 and a = [ 010 , 111 , 001 ] a=[010, 111, 001] a=[010,111,001], then after removing the strings ai and sorting, the result will take the form: [ 000 , 011 , 100 , 101 , 110 ] [000, 011, 100, 101, 110] [000,011,100,101,110]. Thus, the desired median is 100 100 100.

Input

The first line contains an integer t t t ( 1 ≤ t ≤ 1000 1≤t≤1000 1t1000) — the number of test cases. Then, t test cases follow.

The first line of each test case contains integers n n n ( 1 ≤ n ≤ m i n ( 2 m − 1 , 100 ) 1≤n≤min(2^m−1,100) 1nmin(2m1,100)) and m ( 1 ≤ m ≤ 60 1≤m≤60 1m60), where n is the number of strings to remove, and m is the length of binary strings. The next n lines contain a 1 a_1 a1, a 2 a_2 a2,…, a n a_n an — distinct binary strings of length m.

The total length of all given binary strings in all test cases in one test does not exceed 1 0 5 10^5 105.

Output

Print t answers to the test cases. For each test case, print a string of length m — the median of the sorted sequence of remaining strings in the corresponding test case.

Sample Input

5
3 3
010
001
111
4 3
000
111
100
011
1 1
1
1 1
0
3 2
00
01
10

Sample Output

100
010
0
1
11

题意

2 m 2^m 2m个数,依次为 0 , 1 , 2 , . . . . . , 2 m − 1 0,1,2,.....,2^m-1 0,1,2,.....,2m1。从中删除n个数,则还剩 k = 2 m − n k=2^m-n k=2mn个数,求剩下的序列中下标(从0开始)为 ⌊ k − 1 ⌋ 2 \frac{⌊k−1⌋}{2} 2k1的数是多少。

题解

只考虑原序列,则所求为 x = ⌊ 2 m − 1 ⌋ 2 x = \frac{⌊2^m−1⌋}{2} x=22m1。从中删除n个数后,与原先比,结果最多偏移n个。所以可以从 m a x ( 0 , x − n ) max(0, x-n) max(0,xn)开始考虑,找到符合条件的数即可。
设当前枚举的数为 p o s pos pos,则需要求出序列中剩下的比 p o s pos pos小的数的数量num。num等于pos-删除的序列中小于pos的数的数量。若 n u m = = ⌊ k − 1 ⌋ 2 num==\frac{⌊k−1⌋}{2} num==2k1 p o s pos pos即为所求。
(若pos被删除,则跳过)。

#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define eps 1e-6
 
using namespace std;
typedef long long LL;   
typedef pair<int, int> P;
const int maxn = 120;
const int mod = 1000000007;
LL a[maxn];
char str[maxn];
bool isok(LL x, int n);

int main()
{
	int t, n, m, i, j;
	LL num, pos, k;
	scanf("%d", &t);
	while(t--)
	{
		scanf("%d %d", &n, &m);		
		for(i=0;i<n;i++){
			scanf(" %s", str);
			a[i] = 0;
			for(j=0;j<m;j++)
				a[i] = a[i]*2+str[j]-'0';
		}
		sort(a, a+n);
		pos = max(0LL, (1LL<<m)/2-120);
		while(isok(pos, n))
				pos++;
		k = ((1LL<<m)-n-1)/2;
		while(1){
			num = pos - (lower_bound(a, a+n, pos)-a);
			if(num == k)break;
			pos++;
			while(isok(pos, n))
				pos++;
		}
		for(i=m-1;i>=0;i--)
			if(pos&(1LL<<i))printf("1");
			else printf("0");
		printf("\n");
	}
	return 0;
}

bool isok(LL x, int n)
{
	int pos = lower_bound(a, a+n, x)-a;
	if(pos == n || a[pos] != x)return false;
	else return true;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值