Vlad and Division(STL+思维)

105 篇文章 0 订阅
3 篇文章 0 订阅

Vlad and Division

题面翻译

弗拉迪斯拉夫有 n n n 个非负整数,他想把所有这些整数分成几组,这样在任何一组中,从 1 1 1 /-st到 31 31 31 /-st位(即考虑二进制表示的 31 31 31 个最小有效位),任何一对数的位值都不匹配。

对于整数 k k k ,让 k 2 ( i ) k_2(i) k2(i) 表示其二进制表示中的 i i i -th 位(从右到左,从 1 开始索引)。例如,如果 k = 43 k=43 k=43 ,因为 43 = 10101 1 2 43=101011_2 43=1010112 ,那么 4 3 2 ( 1 ) = 1 43_2(1)=1 432(1)=1 4 3 2 ( 2 ) = 1 43_2(2)=1 432(2)=1 4 3 2 ( 3 ) = 0 43_2(3)=0 432(3)=0 4 3 2 ( 4 ) = 1 43_2(4)=1 432(4)=1 4 3 2 ( 5 ) = 0 43_2(5)=0 432(5)=0 4 3 2 ( 6 ) = 1 43_2(6)=1 432(6)=1 4 3 2 ( 7 ) = 0 43_2(7)=0 432(7)=0 4 3 2 ( 8 ) = 0 , … , 4 3 2 ( 31 ) = 0 43_2(8)=0, \dots, 43_2(31)=0 432(8)=0,,432(31)=0

形式上,对于同一组中的任意两个数 x x x y y y ,条件 x 2 ( i ) ≠ y 2 ( i ) x_2(i) \neq y_2(i) x2(i)=y2(i) 必须对所有 1 ≤ i < 32 1 \leq i <32 1i<32 成立。

弗拉德至少需要多少组数字才能实现他的目标?每个数字必须正好属于一组。

输入

第一行包含一个整数 t t t ( 1 ≤ t ≤ 1 0 4 1 \leq t \leq 10^4 1t104 ) - 测试用例数。

每个测试用例的第一行包含一个整数 n n n ( 1 ≤ n ≤ 2 ⋅ 1 0 5 1 \leq n \leq 2 \cdot 10^5 1n2105 ) - 整数总数。

每个测试用例的第二行包含 n n n 给定整数 a 1 , … , a n a_1, \ldots, a_n a1,,an ( 0 ≤ a j < 2 31 0 \leq a_j <2^{31} 0aj<231 )。

测试中所有测试用例的 n n n 之和不超过 2 ⋅ 1 0 5 2 \cdot 10^5 2105

输出

对于每个测试用例,输出一个整数 - 满足条件所需的最小组数。

在第一个测试用例中,任何两个数字的最后 31 31 31 位都是相同的,因此我们需要将每个数字放在自己的组中。

在第二个测试用例中, a 1 = 000000000000000000000000000000 0 2 a_1=0000000000000000000000000000000_2 a1=00000000000000000000000000000002 a 2 = 111111111111111111111111111111 1 2 a_2=1111111111111111111111111111111_2 a2=11111111111111111111111111111112 可以放在同一组中,因为在 1 1 1 31 31 31 (含)之间的每个 i i i 都有 a 1 ( i ) ≠ a 2 ( i ) a_1(i) \ne a_2(i) a1(i)=a2(i)

翻译:@tXX_F

题目描述

Vladislav has $ n $ non-negative integers, and he wants to divide all of them into several groups so that in any group, any pair of numbers does not have matching bit values among bits from $ 1 $ -st to $ 31 $ -st bit (i.e., considering the $ 31 $ least significant bits of the binary representation).

For an integer $ k $ , let $ k_2(i) $ denote the $ i $ -th bit in its binary representation (from right to left, indexing from 1). For example, if $ k=43 $ , since $ 43=101011_2 $ , then $ 43_2(1)=1 $ , $ 43_2(2)=1 $ , $ 43_2(3)=0 $ , $ 43_2(4)=1 $ , $ 43_2(5)=0 $ , $ 43_2(6)=1 $ , $ 43_2(7)=0 $ , $ 43_2(8)=0, \dots, 43_2(31)=0 $ .

Formally, for any two numbers $ x $ and $ y $ in the same group, the condition $ x_2(i) \neq y_2(i) $ must hold for all $ 1 \leq i < 32 $ .

What is the minimum number of groups Vlad needs to achieve his goal? Each number must fall into exactly one group.

输入格式

The first line contains a single integer $ t $ ( $ 1 \leq t \leq 10^4 $ ) — the number of test cases.

The first line of each test case contains a single integer $ n $ ( $ 1 \leq n \leq 2 \cdot 10^5 $ ) — the total number of integers.

The second line of each test case contains $ n $ given integers $ a_1, \ldots, a_n $ ( $ 0 \leq a_j < 2^{31} $ ).

The sum of $ n $ over all test cases in a test does not exceed $ 2 \cdot 10^5 $ .

输出格式

For each test case, output a single integer — the minimum number of groups required to satisfy the condition.

样例 #1

样例输入 #1

9
4
1 4 3 4
2
0 2147483647
5
476319172 261956880 2136179468 1671164475 1885526767
3
1335890506 811593141 1128223362
4
688873446 627404104 1520079543 1458610201
4
61545621 2085938026 1269342732 1430258575
4
0 0 2147483647 2147483647
3
0 0 2147483647
8
1858058912 289424735 1858058912 2024818580 1858058912 289424735 122665067 289424735

样例输出 #1

4
1
3
2
2
3
2
2
4

提示

In the first test case, any two numbers have the same last $ 31 $ bits, so we need to place each number in its own group.

In the second test case, $ a_1=0000000000000000000000000000000_2 $ , $ a_2=1111111111111111111111111111111_2 $ so they can be placed in the same group because $ a_1(i) \ne a_2(i) $ for each $ i $ between $ 1 $ and $ 31 $ , inclusive.

思路

如果我们暴力去枚举肯定超时,我们不妨求一边不就行了。

其实我们还是可以发现一些性质的:

  • 所以一组最多只能有 2 2 2 个数。

那么代码就很好写了:

代码

//枚举相反的
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<limits.h>

using namespace std;

const int N = 2e5+10;

int w[N];
int n,T;

int main(){
    cin>>T;
    
    while(T--){
        cin>>n;
        
        map<int,int>S;
        
        for(int i=1;i<=n;i++){
            cin>>w[i];
            S[w[i]]++;
        }
        
        int m=n;
        int cnt=0;
        
        for(auto& [v,w]:S){
            int t=INT_MAX^v,m=min(w,S[t]);
            w-=m;
            S[t]-=m;
            cnt+=m;
        }
        
        for(auto& [v,w]:S){
            cnt+=w;
        }
        
        cout<<cnt<<endl;
        
        
    }
    
    return 0;
}
  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

green qwq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值