纪中暑假集训 2020.08.07【NOIP提高组】模拟 T3:【佛山市选2013】海明距离

【佛山市选2013】海明距离

Description

对于二进制串a,b,他们之间的海明距离是指两个串异或之后串中1的个数。异或的规则为:

0 XOR 0 = 0

1 XOR 0 = 1

0 XOR 1 = 1

1 XOR 1 = 0

计算两个串之间的海明距离的时候,他们的长度必须相同。现在我们给出N个不同的二进制串,请计算出这些串两两之间的最短海明距离。

Input

第一个数字是整数T(T≤10),代表数据的组数。

接下来有T组数据,每组数据的第一行是一个正整数N,代表不同的二进制串的个数。接下来是N行,每行都是一个二进制串(长度是5)。我们用数字(0-9)和字符(A-F)来表示这个二进制串。它代表这个二进制串的16进制码。例如,“12345”代表的二进制串为“00010010001101000101”。

Output

对于每个数据,请输出一个整数,即答案值。

Sample Input

2

2

12345

54321

4

12345

6789A

BCDEF

0137F

Sample Output

6

7

反思&题解

比赛思路: 暴力……
正解思路: 01trie可以轻松过,但是有个大大大大大大大大大……水法,直接取前1000个两两异或统计答案就可以过了,本人亲测有效。(好像用组合数是可以证明卡这个方法很难的,而且不管怎么卡再打几个特判也还是可以过)
反思: 突然感觉位运算的题好像都那么多可以水的???

CODE

var
        t,n,i,j,tot,tt,k,sum,num,ans:longint;
        a:array[0..100005]of longint;
        s:string;
function power(x,y:longint):longint;
var
        tot:longint;
begin
        tot:=1;
        while y>0 do
        begin
                if (y and 1)=1 then tot:=tot*x;
                y:=y>>1;
                x:=x*x;
        end;
        exit(tot);
end;
function min(x,y:longint):longint;
begin
        if x<y then exit(x)
        else exit(y);
end;
begin
        readln(t);
        while t>0 do
        begin
                readln(n);
                tot:=0;
                fillchar(a,sizeof(a),0);
                for i:=1 to n do
                begin
                        readln(s);
                        for j:=1 to 5 do
                        begin
                                if (s[j]>='0')and(s[j]<='9') then tt:=ord(s[j])-48
                                else tt:=ord(s[j])-55;
                                a[i]:=a[i]+tt*power(16,5-j);
                        end;
                end;
                ans:=12345678;
                for i:=1 to min(1000,n)-1 do
                begin
                        for j:=i+1 to min(1000,n) do
                        begin
                                sum:=a[i] xor a[j];
                                num:=0;
                                for k:=0 to 19 do
                                begin
                                        if (sum and (1<<k))>0 then inc(num);
                                end;
                                ans:=min(ans,num);
                        end;
                end;
                writeln(ans);
                dec(t);
        end;
end.

猜你喜欢

转载自blog.csdn.net/CMC_YXY/article/details/107880509