|
本帖最后由 newkid 于 2023-1-26 00:38 编辑
----------------
#7 PAWNS 新思路:改良过的暴力法,利用推理把关注范围缩小到用代码可以求出结果。纯推理方法应该也有但是我没想出来。
把图中的每一列看作一个九位二进制数,假设S是一个满足条件的最大集,每个元素就是其中一个9位二进制数,任意两个元素的XOR结果至少有5个二进制位为1。
推论:要么#1: S里面包含全零,要么#2: 可以找到另外一个一样大的集合,里面包含全零。
#2证明:假设S本身不包含全零,则任取一个元素C作为基准,把集合中所有的元素全部XOR C,那么C就变成了全零,而集合仍然满足条件。因为本来任意两个元素AB, A XOR B 满足条件,现在分别XOR C,就变成了了 A XOR C XOR B XOR C,C和C互相抵消,结果仍然是A XOR B
把全零作为一个基本元素,则最大集可以分别为以下两种情况:
#1:包含四个零(其他元素可能含有一个,两个,三个零);
#2:不含四个零,但含三个零(其他元素可能有两个零,但不含一个零,一个零和三个零XOR就凑不出五个1);
全1不可以出现。任意一个A,不可能和全零XOR满足条件,同时和全1 XOR也满足条件。
不可能包含五个以上的零(因为和全零异或之后,1不够5位)
也不可能只有两个或一个零,因为凑不出五个1,XOR抵消了。
图中的行顺序是和结果无关的。给定一个集合,任意调换所有元素所在的同一行,不影响结果。假设有一个元素包含四个零,那么可以通过调换把四个零全部排在最上面,或者最下面,而不影响结果(注意在调换时所有元素所在的同一行必须一起调换)。由于这个原因,满足条件的最大集有很多个,但它们都是类似的,我们只需关注其中一个。
#1:
集合中已经有两个基本元素:
A:000011111
B:000000000
构造其他候选元素:
四个零: 最多只能有一个零出现在左边四位中。如果有2,3,4个零出现在左边四位,那么和A的XOR就凑不够五个1。
左边零的位置:四种,右边C(5,3),所以总共有4*C(5,3)=40
或者四个零全在右边,共有C(5,4)=5种
三个零:只能有一个零出现在左边四位中。如果有2,3个零出现在左边四位,那么和A的XOR就凑不够五个1。
左边零的位置:四种,右边C(5,2),所以总共有4*C(5,2)=40
或者三个零全在右边,共有C(5,3)=10种
两个零:两个零必须全在右边,共有C(5,2)=10种
一个零:这个零必须在右边,共有C(5,1)=5种
共计110种, 用110位二进制表示,ORACLE的NUMBER可以支持。
create table e(e varchar2(10), id number,bit number, e2 number);
insert into e(e,id,bit,e2)
with n as (select level n from dual connect by level<=5)
,L1 as (select regexp_replace('1111','1','0',level,1) s1 from dual connect by level<=4) --- 左边一个零
,R3 AS (select lpad(power(10,n1.n-1)+power(10,n2.n-1),5,'0') s2 ---- 三个零(两个1)在右边
from n n1,n n2
where n1.n<n2.n
)
,R2 AS (select lpad(11111-TO_NUMBER(S2),5,'0') s2 ---- 两个零(三个1)在右边
from R3
)
,s as (
select e,row_number() over(order by e) as id,power(2,row_number() over(order by e)-1) as bit from
(
---------- 四个零的情形
select L1.s1||r3.s2 as e
from L1 --- 左边一个零, 三个零(两个1)在右边
,r3
UNION ALL
select '1111'||regexp_replace('00000','0','1',level,1) s2 from dual connect by level<=5 ---左边全1, 右边四个零
---------- 三个零的情形
UNION ALL
SELECT L1.s1||r2.s2
FROM L1 --- 左边一个零, 两个零(三个1)在右边
,r2
UNION ALL ---- 左边全1, 三个零(两个1)在右边
select '1111'||s2
FROM R3
---------- 两个零的情形
UNION ALL ---- 左边全1, 两个零(三个1)在右边
select '1111'||s2
FROM R2
---------- 一个零的情形
UNION ALL
select '1111'||regexp_replace('11111','1','0',level,1) from dual connect by level<=5
)
)
select e,id,bit,sum(bit2) as e2 ------- 所有和当前边异或之后满足条件的其他边的二进制位之和
from (
select e1.*,e2.bit bit2,replace(lpad(to_number(e1.e)+to_number(e2.e),9,'0'),'2','0') xor
from s e1,s e2
where e1.id<>e2.id
)
where regexp_count(xor,'1')>=5
group by e,id,bit;
with t(s,cnt,bit,last_id) as (
select cast(id as varchar2(100)),1,e2,id from e
union all
select t.s||','||e.id,t.cnt+1,bitand(t.bit,e.e2),e.id
from t,e
where bitand(t.bit,e.bit)>0
and t.last_id<e.id
)
select * from (select * from t order by cnt desc,s) where rownum=1;
S
--------------------------------------
CNT BIT LAST_ID
---------- ---------- ----------
1,28,55,79
4 0 79
select S from e where e.id in (1,28,55,79);
E
----------
011100011
101101100
110110101
111011010
#2:
集合中已经有两个基本元素:
A:000111111
B:111111111
构造其他候选元素:
三个零:三个零必须全在右边,共有C(6,3)=20种
两个零:两个零必须全在右边,共有C(6,2)=15种
共计35种, 用35位二进制表示,ORACLE的NUMBER可以支持。
DELETE e;
-- create table e(e varchar2(10), id number,bit number, e2 number);
insert into e(e,id,bit,e2)
with n as (select level n from dual connect by level<=6)
,s as (
select e,row_number() over(order by e) as id,power(2,row_number() over(order by e)-1) as bit from
(
select '111'||lpad(power(10,n1.n-1)+power(10,n2.n-1)+power(10,n3.n-1),6,'0') e ---- 三个零(三个1)在右边
from n n1,n n2,n n3
where n1.n<n2.n and n2.n<n3.n
UNION ALL
select '111'||lpad(power(10,n1.n-1)+power(10,n2.n-1)+power(10,n3.n-1)+power(10,n4.n-1),6,'0') s2 ---- 两个零(四个1)在右边
from n n1,n n2,n n3,n n4
where n1.n<n2.n and n2.n<n3.n and n3.n<n4.n
)
)
select e,id,bit,sum(bit2) as e2 ------- 所有和当前边异或之后满足条件的其他边的二进制位之和
from (
select e1.*,e2.bit bit2,replace(lpad(to_number(e1.e)+to_number(e2.e),9,'0'),'2','0') xor
from s e1,s e2
where e1.id<>e2.id
)
where regexp_count(xor,'1')>=5
group by e,id,bit;
------ 以下代码同上面"四个零"的情形
with t(s,cnt,bit,last_id) as (
select cast(id as varchar2(100)),1,e2,id from e
union all
select t.s||','||e.id,t.cnt+1,bitand(t.bit,e.e2),e.id
from t,e
where bitand(t.bit,e.bit)>0
and t.last_id<e.id
)
select * from (select * from t order by cnt desc,s) where rownum=1;
S
------------------------------
CNT BIT
---------- ----------
1,32
2 0
所以S最大为6个元素:
011100011
101101100
110110101
111011010
000011111
000000000
这个答案比想象中的小,不知道上面推理过程有没有错误。
|
|