1. 程式人生 > >[CQOI2013]新Nim遊戲

[CQOI2013]新Nim遊戲

回合 class bre 最大的 證明 tput 沒有 屬於 cstring

Description

傳統的Nim遊戲是這樣的:有一些火柴堆,每堆都有若幹根火柴(不同堆的火柴數量可以不同)。兩個遊戲者輪流操作,每次可以選一個火柴堆拿走若幹根火柴。可以只拿一根,也可以拿走整堆火柴,但不能同時從超過一堆火柴中拿。拿走最後一根火柴的遊戲者勝利。 本題的遊戲稍微有些不同:在第一個回合中,第一個遊戲者可以直接拿走若幹個整堆的火柴。可以一堆都不拿,但不可以全部拿走。第二回合也一樣,第二個遊戲者也有這樣一次機會。從第三個回合(又輪到第一個遊戲者)開始,規則和Nim遊戲一樣。 如果你先拿,怎樣才能保證獲勝?如果可以獲勝的話,還要讓第一回合拿的火柴總數盡量小。

Input

第一行為整數k。即火柴堆數。第二行包含k個不超過109的正整數,即各堆的火柴個數。

Output

輸出第一回合拿的火柴數目的最小值。如果不能保證取勝,輸出-1。

Sample Input

6
5 5 6 6 5 5

Sample Output

21

HINT

k<=100

可知異或和為0則必敗,也就是說開頭取掉幾堆後,剩余集合不能出現異或為0的子集

可知就是維護一個權值和最大的線性無關組(線性基)

從大到小排序,一個個加入線性基

如果沒有成功插入,那麽說明該元素與其他線性相關,即可以用線性基中的子集異或和表示

這和元素的貪心很像

給出擬陣證明

我們設n個火柴堆的數目為集合S,若某個S的子集r不存在任何一個非空子集異或和0,則r∈I.下面我們證明二元組M=(S,I)是一個擬陣。
遺傳性:設A∈I,則A是S的線性無關組,則A的任意非空子集均線性無關,即對A的任意子集B,B均線性無關,因此B∈I,證畢。
交換性:設A,B∈I,且|A|<|B|,我們要證明存在x∈B,使得A∪{x}∈I.利用反證法,假設對於任意x∈B-A,均有A∪{x}不屬於I,則B-A中的元素均在A的異或空間中,可由A的子集異或和表示。
因此B中的元素都在A的異或空間中。那麽必然有B的異或空間包含於A的異或空間。由|A|<|B|且A,B線性無關,顯然矛盾。因此交換性存在,證畢。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 typedef long long lol;
 8 int P[40],a[101],n;
 9 lol ans;
10 int add(int x)
11 {int i;
12   for (i=30;i>=0;i--)
13     if (x&(1<<i))
14       {
15     if (P[i]==0)
16       {
17         P[i]=x;
18         break;
19       }
20     x^=P[i];
21       }
22   return x;
23 }
24 int main()
25 {int i;
26   cin>>n;
27   for (i=1;i<=n;i++)
28     scanf("%d",&a[i]);
29   sort(a+1,a+n+1);
30   for (i=n;i>=1;i--)
31     {
32       if (add(a[i])==0) ans+=a[i];
33     }
34   cout<<ans;
35 }

[CQOI2013]新Nim遊戲