usaco4.1.1Beef McNuggets

麥香牛塊

描述

農夫布朗的奶牛們正在進行鬥爭,因爲它們聽說麥當勞正在考慮引進一種新產品:麥香牛塊。奶牛們正在想盡一切辦法讓這種可怕的設想泡湯。奶牛們進行鬥爭的策略之一是“劣質的包裝”。“看,”奶牛們說,“如果你只用一次能裝3塊、6塊或者10塊的三種包裝盒包裝麥香牛塊,你就不可能滿足一次只想買1、2、4、5、7、8、11、14或者17塊麥香牛塊的顧客了。劣質的包裝意味着劣質的產品。”

你的任務是幫助這些奶牛。給出包裝盒的種類數N(1<=N<=10)和N個代表不同種類包裝盒容納麥香牛塊個數的正整數(1<=i<=256),輸出顧客不能用上述包裝盒(每種盒子數量無限)買到麥香牛塊的最大塊數。如果所有購買方案都能得到滿足或者不存在不能買到塊數的上限,則輸出0。 不能買到的最大塊數(倘它存在)不超過2,000,000,000。

[編輯]格式

PROGRAM NAME: nuggets

INPUT FORMAT:

(file nuggets.in)

第1行: 包裝盒的種類數N

第2行到N+1行: 每個種類包裝盒容納麥香牛塊的個數

OUTPUT FORMAT:

(file nuggets.out)

輸出文件只有一行數字:顧客不能用包裝盒買到麥香牛塊的最大塊數或0(如果所有購買方案都能得到滿足或者顧客不能買到的塊數沒有上限)。

[編輯]SAMPLE INPUT

3
3
6
10

[編輯]SAMPLE OUTPUT

17


題解:

竟然是一個數論加水揹包2333

粘貼題解(=_=)

數論的結論

只要你知道以下的數論結論,這道題就是水揹包了:

有兩個數p,q,且gcd(q,p)=1,則最大無法表示成px+qy(x>=0,y>=0)的數是pq-q-p(對於n>pq-q-p,都可以表示成px+qy;而pq-q-p,就無法表示成px+qy)。

而且數越多,這個值只會越小。

所以我們只需考慮小於pq-q-p的範圍的最小值。對於一些無解的(全體最大公約數>1),或無數解的(有一個‘1’),應提前判斷。 其實我們可以乾脆全取上界爲256*256-256*2。

證明:

假設可以表示爲pq-q-p

那麼

px+qy=pq-q-p

p(x+1)+q(y+1)=pq

p|y+1, q|x+1

又p(x+1),q(y+1)<=pq

有(x+1=kq且y+1=(1-k)q)或(x+1=(1-k)p,且y+1=kp),k是正整數

但是x,y>=0故pq-q-p,就無法表示成px+qy

2.

(p-1)(q-1)=pq-p-q+1

對於n>pq-q-p即n>=(q-1)(p-1)

gcd(p,q)=1

對於z<min{p,q}存在a,b使得ap+bq=z

不妨設a>0>b,顯然a>0

那麼如果a>q,取a1=a-q,b1=b+p

那麼有a1*p+b1*q=z.

如果a1>q,可以繼續以得到

Ap+Bq=z,且0<|A|<q,0<|B|

pq-q-p n=pq-q-p+k*min{p,q}+r r<z<min{p,q} 那麼取A,B Ap+Bq=r,且0<|A|<q,0<|B|<p 不妨設A>0 n=pq-q-p+k*min{p,q}+r =(q-1)p-p+k*min{p,q}+Ap+Bq =(A-1)p+(B+q-1)p+k*min{p,q} 其中(A-1),(B+q-1)>=0 那麼無論min{p,q}是p還是q,都有 對於n>pq-q-p,都可以表示成px+qy ——whx


上述論斷的失敗

請注意,上述證明是錯誤的,即便(很可能)在一切實際情形下上述上界均成立。

問題的關鍵在於何時可以使用最小公倍數上界。有一個重要的條件:p和q互素。很容易構造一組最大公約數爲1但兩兩不互素的數,最簡單的是:(2*3=6, 3*5=15, 5*2=10),較接近題述上限的一組是(250, 252, 255) (該組數據運行結果爲13253,仍在上述上界之內)。

[編輯]問題分析

這是一個揹包問題。一般使用動態規劃求解。

一種具體的實現是:用一個線性表儲存所有的節點是否可以相加得到的狀態,然後每次可以通過一個可以相加得到的節點,通過加上一個輸入的數求出新的可以相加得到的點。複雜度是O(N×結果)。

但是可以證明結果不會超過最大的兩個數的最小公倍數(如果有的話)。參見數論。所以複雜度也是O(Na2),完全可以接受了。

判斷無限解可以按上面的方法,另外也可以算所有的數的最大公約數。如果不是1,也就是說這些數不互質,那麼不被這個最大公約數整除的數一定構造不出來。當且僅當這種情況會有無限解。另外有一種不需要任何數論知識的方法是判斷是不是按照每個輸入的數的循環節循環,如果是的話,繼續算顯然不會有任何結果。

判斷有沒有更大的解也可以按這種方法,另外如果連續最小的數那麼多個數都可以構成,也不會有更大的符合條件的解。

通過位壓縮可以使程序在32位機上的運行速度快32倍(由於程序代碼會變長,也可能是16倍或者更小的倍數)。這樣可以相當快的解決這個問題。不過複雜度還是O(Na2)。

“可以證明結果不會超過最大的兩個數的最小公倍數”。我來證明一下。

已知,不定方程 ax + by = c ( a , b > 0 且 c >= ab )存在一組整數解( x0 , y0 ) (裴蜀定理)

求證,該不定方程存在一組非負整數解 ( xn , yn ) .

證明 : 由不定方程通解式得 : xn = x0 + b * t , yn = y0 - a * t ( t 是整數 )

令 xn , yn >= 0 解出 - ( x0 / b ) <= t <= ( y0 / a )

因爲 c >= a * b 即 a * x0 + b * y0 >= a * b 兩邊同除 a * b 得 :

y0 / a - ( - x0 / b ) >= 1

所以一定存在 整數t使得 - ( x0 / b ) <= t <= ( y0 / a ) .

所以方程一定有非負整數解. 證畢.

[編輯]特殊情況

  1. 無解的情況:很顯然,只有輸入的N個數裏有1的情況纔會無解,否則1本身就是一個解,因爲沒辦法由更大的數相加得到。
  2. 無限個解的情況,見上面的#問題分析

對於這道題目,這兩種情況都應該輸出0

注:如果有兩個連續的數x,x+1 在序列中的話,那(x-1)*x以後的數都能通過這兩個相加得到。所以如果(x-1)*x前無解,則無解!

[編輯]相關題目及擴展

主條目:揹包問題

這是一道很簡單的揹包問題。在複雜度證明中需要少量的數論知識,不過不會數論也可以解決這個問題。

這道題相對於同在USACO這一章的兩道搜索題Fence Rails(也是多個揹包問題)以及Cryptcowgraphy,已經是相當簡單了!

[編輯]不用揹包的其他方法

如果已經證明,在有限解的情況下,解的範圍一定小於256^2的話,那麼,就可以採用構造法了,最壞複雜度是(256^2)*10。

對於無限解:

  • 如果輸入數據中有1,爲無限解。
  • 如果某個大於256^2的數不能被合成,爲無限解。並且可以證明,這個數字一定小於等256^2+256。

抱歉,我無法給出一個非常嚴謹數學證明,只有僞證明。

僞證明:設x是1~256^2中最大的一個能被合成的數,min(q[i])是輸入數據中最小的一個,那麼,x+min(q[i])-1就不能被合成,由於沒有1.

所以,本題用構造的方法就可以解決。

TASK: nuggets
LANG: PASCAL

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.000 secs, 272 KB]
   Test 2: TEST OK [0.000 secs, 272 KB]
   Test 3: TEST OK [0.000 secs, 268 KB]
   Test 4: TEST OK [0.000 secs, 268 KB]
   Test 5: TEST OK [0.000 secs, 272 KB]
   Test 6: TEST OK [0.000 secs, 272 KB]
   Test 7: TEST OK [0.011 secs, 268 KB]

關鍵代碼:

  f[0]:=true;
  for i:=0 to 65536 + 256 do
    if f[i] then
     begin
      for j:=1 to n do
        f[i+a[j]] :=true;
      end
            else
      m:=i;
  if m<=65536 then 
  writeln(m)  else
  writeln(0);

[編輯]參見



優化算法 這道題其實是可以做到O(N^2)。 令A1表示所有雞塊中最小的那種, 如果有連續A1個數都可以打到,那麼之後所有的數都是可以達到的(每次加上A1就行了)。

 S[ I ] = { X | X % A1 = I 且可以 X 可以達到 }
 F[ I ] = MIN{ X |( X * A1 + I )屬於S[ I ] }

如果任意F[ I ] = 0 那麼表示所有數都可以被構造,就輸出0啦。 如果存在F[ I ] = +OO 那麼表示所有餘數爲I的都不可以被構造,也就輸出0啦。

至於F[ I ]的求法可以使用最短路算法。 建立有向圖,點分別編號爲0 --- A1-1, 如果 ( I + AX )% A1 = J , 那麼從節點I向節點J連一條有向邊,距離爲1. DIST[ I ] 即 F[ I ]


單源最短路算法是O(N^2) 故此算法O(N^2)


評論:

個人感覺

“”如果 ( I + AX )% A1 = J , 那麼從節點I向節點J連一條有向邊,距離爲1.“”

距離應爲 (I + AX) div A1

因爲如果小於的話,f是不會增加的,距離應爲1

另外複雜度應爲O(A1*N)

[編輯]另一種解法

我認爲,可以得到的牛塊,如果可以得到mod 第一個數字(不妨設它爲x),那麼,也可以得到 mod x+y的(y爲任意一個數字) 對於每輸入一個y,就可以進行x*x次這種更新,可以保證他是對的。(x種順序不好確定) 更新完畢後,再輸入下一個 如果有一個mod x==inf,那麼就是無窮解,輸出0,否則直接輸出其中的最大值-x就行了(注意:我們得到的是最小可行的解,不是最大不可行的)





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章