你就是乙個畫家!你現在想繪製一幅畫,但是你現在沒有足夠顏色的顏料。為了讓問題簡單,我們用正整數表示不同顏色的顏料。你知道這幅畫需要的n種顏色的顏料,你現在可以去商店購買一些顏料,但是商店不能保證能**所有顏色的顏料,所以你需要自己混合一些顏料。混合兩種不一樣的顏色a和顏色b顏料可以產生(a xor b)這種顏色的顏料(新產生的顏料也可以用作繼續混合產生新的顏色,xor表示異或操作)。本著勤儉節約的精神,你想購買更少的顏料就滿足要求,所以兼職程式設計師的你需要程式設計來計算出最少需要購買幾種顏色的顏料?
輸入描述:
第一行為繪製這幅畫需要的顏色種數n (1 ≤ n ≤ 50)
第二行為n個數xi(1 ≤ xi ≤ 1,000,000,000),表示需要的各種顏料.
輸出描述:
輸出最少需要在商店購買的顏料顏色種數,注意可能購買的顏色不一定會使用在畫中,只是為了產生新的顏色。
示例1
輸入
3 1 7 3
輸出
3首先分析題目給出的示例1
輸入為1 7 3
你可以購買1,2,4這三種顏料,1已經有了,3可以通過由 1 xor 2 = 3得到,7可以通過1 xor 4 = 5,5 xor 2 = 7 得到,所以最少為3種。
理解1
想象一下對於兩個給定的數(向量),他們可以生成的新的數,本質就是兩個向量的所有線性表示。因為此處實際是在做乙個mod 2的操作,那麼線性表示的係數就是0或1。 於是原問題就抽象為,給定一些向量(數)組成的向量空間,增加乙個最小的向量集合,使向量的線性組合都可以生成向量空間中的所有向量。這個叫做向量空間的基。
怎麼算出這個基呢?線性代數裡面我們都學過:可以對原來所有向量組成的矩陣用高斯消元法直到讓剩餘的向量都是線性無關的,非0向量的個數就是答案。每次將最高位的1進行^運算,使得陣列裡面從後往前數最高位每個1只保留乙個,最終得到類似於這樣的結構,那麼答案就出來了。
理解2
給定多個數字,將這些數之間進行多次xor(異或操作),其中乙個數可能被xor多次,看最後能剩餘多少不重複的數(任何兩個數字異或都沒有出現在現在的陣列中),這些不重複的數字就是一組基,輸出數量即可。這種方法可以用暴力求解。
一些規律(下面會用到)
1.0001,0010,0100,1000(這四個數」線性無關」,注意運算規則是異或(和線性代數有區別),任意兩個陣列進行xor運算結果都不在這個陣列中,也即是乙個基,可以表示任何4位數),可以通過^生成任意4位的數字
2.a^b=c那麼a^c=b
這道題見過的最簡潔的解法
#include
#include
using
namespace
std;
int main()
for(i=0;x[i]==0;++i); //陣列是從小到大排列的,記錄第乙個不為0的索引
cout
return
0;}
網易筆試程式設計題 混合顏料
題目描述 你就是乙個畫家!你現在想繪製一幅畫,但是你現在沒有足夠顏色的顏料。為了讓問題簡單,我們用正整數表示不同顏色的顏料。你知道這幅畫需要的n種顏色的顏料,你現在可以去商店購買一些顏料,但是商店不能保證能 所有顏色的顏料,所以你需要自己混合一些顏料。混合兩種不一樣的顏色a和顏色b顏料可以產生 a ...
2017校招 混合顏料
題目描述 2017校招 混合顏料 你就是乙個畫家!你現在想繪製一幅畫,但是你現在沒有足夠顏色的顏料。為了讓問題簡單,我們用正整數表示不同顏色的顏料。你知道這幅畫需要的n種顏色的顏料,你現在可以去商店購買一些顏料,但是商店不能保證能 所有顏色的顏料,所以你需要自己混合一些顏料。混合兩種不一樣的顏色a和...
程式設計測試題 混合顏料
你就是乙個畫家!你現在想繪製一幅畫,但是你現在沒有足夠顏色的顏料。為了讓問題簡單,我們用正整數表示不同顏色的顏料。你知道這幅畫需要的n種顏色的顏料,你現在可以去商店購買一些顏料,但是商店不能保證能 所有顏色的顏料,所以你需要自己混合一些顏料。混合兩種不一樣的顏色a和顏色b顏料可以產生 a xor b...