2020杭電多校 9C / HDU 6869 - Slime and Stones (線性遞推/威佐夫博弈)


HDU 6869 - Slime and Stones


題意

有兩堆石子,數量分別為\(a,b\),兩人輪流取,每次必須取一個及以上的石子

每次可以任選一堆取(個數不限),也可以兩堆都取(取的個數差值必須\(\leq k\)

兩人都以最優策略取石子,問是否存在一種情況使得先手必勝,是則輸出\(1\),否則輸出\(0\)


限制

\(1\leq T\leq 10^5\)

\(1\leq a,b\leq 10^8,\ 0\leq k\leq 10^8\)




賽時思路

這部分解法可能是現場賽幾乎不可能實現的寫法吧

  • 下文令\((x,y)\)表示現在兩堆石子的數量,限制\(x\leq y\)

首先考慮最小數據的必敗態

根據題意可以得知,誰將某一堆石子取完,那么他的對手就可以取完另外一堆,所以這種方式必敗

或者如果兩堆石子數量差在\(k\)之內(\(|a-b|\leq k\)),那么就可以直接拿走兩堆內所有石子並獲勝

所以可以得到,如果較少的堆內剩余\(1\)粒石子,較多的堆內剩余\(k+2\)粒,那么當前不論怎么操作都會輸掉這場比賽

得到:\((1,k+2)\)為最小數據下的必敗態

為了找到規律,我們枚舉兩堆石子中較少堆的數量


當較少的堆中僅存在\(1\)粒石子時——

當剩余情況為\((1,i),\ 1\leq i\leq k+1\)時,當前操作的人可以直接拿完兩堆,所以必勝

當剩余情況為\((1,k+2)\)時,必敗

當剩余情況為\((1,i),\ i\geq k+3\)時,當前操作的人可以將其轉換到\((1,k+2)\)的情況,所以必勝


相同的,當較少的堆中僅存在\(2\)粒石子時——(這里不適用於\(k=0\)的情況)

當剩余情況為\((2,i),\ 2\leq i\leq k+2\)時,當前操作的人可以直接拿完兩堆,所以必勝

當剩余情況為\((2,i),\ k+3\leq i\leq 2k+3\),將較少的堆拿去\(1\)粒,較大的堆最多可以拿\(k+1\)粒,所以可以轉移到\((1,k+2)\)的狀態,所以必勝

當剩余情況為\((2,2k+4)\)時,必敗

當剩余情況為\((2,i),\ i\geq 2k+5\)時,當前操作的人可以將其轉換到\((2,2k+4)\)的情況,所以必勝


直到較少的堆內存在\(k+2\)粒石子時,情況發生了變化——

當剩余情況為\((k+2,i),\ k+2\leq i\leq 2k+3\)時,當前操作的人可以直接拿完兩堆,必勝

當剩余情況為\((k+2,i),\ i\geq 2k+4\)時,發現前面有個必敗態\((1,k+2)\),他們共享\(k+2\)這個狀態,所以可以從\((k+2,2k+4)\)直接轉換到\((1,k+2)\)的狀態,所以該情況下必勝


綜上,可以得到的一個規律就是

后面的一個必敗態總是可以由前一個必敗態推導而來

假設\((x,y)\)是一個必敗態,假設較小的堆被拿了\(1\)粒石子,那么較大的堆最多能拿\(k+1\)粒石子

顯然,\((x+1,y+k+2)\)無法僅通過一步就推到\((x,y)\),可能必敗

還要考慮一點,就是\(x+1\)沒有在前面的任意必敗態中出現過,否則可以直接一步轉移到更前面的必敗態,使得該點必勝

如果\(x+1\)並未出現在前面任意一個必敗態中,就可以肯定\((x+1,y+k+2)\)無法轉移到任意一個必敗態,則它不是必勝態,是一個必敗態


\(k=1\)的情況為例,最小必敗態為\((1,3)\)

考慮\((x+1,y+k+2)\)的轉移方式,顯然\(x+1=2\)並未出現在前面任意一個必敗態中

所以\((2,6)\)是一個必敗態

繼續考慮,發現下一個狀態為\((3,9)\)

但是\(3\)存在於必敗態\((1,3)\)內,說明\((3,9)\)可以直接轉換到\((1.3)\),這是個必勝態

為了讓其不能一遍轉移得到,則可以假設兩堆都多取了一粒石子,即考慮\((x+1+1,y+k+2+1)\)

發現\(2+1+1=4\)並未出現,所以\((4,10)\)是一個必敗態

一直這樣考慮下去,粗略得到\(k=1\)的必敗態分布情況為

\[(1,3)\\(2,6)\\(4,10)\\(5,13)\\(7,17)\\ (8,20)\\(9,23)\\(11,27)\\(12,30)\\(14,34)\\ (15,37)\\(16,40)\\(18,44)\\(19,47)\\(21,51)\\ (22,54)\\(24,58)\\(25,61)\\(26,64) \]

觀察這個分布,得到一個規律:

\((a,b)\)\(b-a\)值以\(2,4,6,8,10,12,14,16,18,20,\dots\)遞增

這可能是一個入手點,那么我們把\(k=0\)的表打出來試試


\(k=0\)時,最小數據必敗態為\((1,2)\)

按規律打表如下

\[(1,2)\\(3,5)\\(4,7)\\(6,10)\\(8,13)\\ (9,15)\\(11,18)\\(12,20)\\(14,23)\\(16,26)\\ (17,28)\\(19,31)\\(21,34)\\(22,36)\\(24,39)\\ (25,41)\\(27,44) \]

得到\(b-a\)的值以\(1,2,3,4,5,6,7,\dots\)遞增


可以得到,\(b-a\)的值是一個首項為\(k+1\),公差為\(k+1\)的等差數列

所以我們可以根據\(\frac {b-a}{k+1}\)來確定某個狀態在必敗態中的項數

如果你想問為什么要求出項數,看下面……


實際上打出表就能發現

必敗態的\(b\)數值分布存在一個規律(\(b_i-b_{i-1}\in\{k+2,k+3\}\)

假如這個\(\{b\}\)數列存在着通項公式,那么肯定是形如\(b_i=\lfloor i\times k\rfloor,\ k\in\R\)

這樣才能保證前后兩項差值固定在一個集合內(雖然這個常數\(k\)可能很難表示)

那么我們就大膽着手於找通項公式

這里開始往下應該也可以采用線性遞推模板解決,不過我沒試過,不確定會不會被卡

打開OEIS,准備嘗試玄學求出可能的通項(這是個能根據數列前幾項或者中間幾項求出通項公式的工具)

但不同的\(k\)肯定對應着不同的通項公式,所以我們再把\(k=2,3,4\)的表稍微打出前幾項


\(k=2\)時,必敗態為

\[(1,4)\\(2,8)\\(3,12)\\(5,17)\\(6,21)\\ (7,25)\\(9,30)\\(10,34)\\(11,38)\\(13,43)\\ (14,47)\\(15,51)\\(16,55) \]

\(k=3\)時,必敗態為

\[(1,5)\\(2,10)\\(3,15)\\(4,20)\\(6,26)\\ (7,31)\\(8,36)\\(9,41)\\(11,47)\\(12,52)\\ (13,57)\\(14,62) \]

\(k=4\)時,必敗態為

\[(1,6)\\(2,12)\\(3,18)\\(4,24)\\(5,30)\\ (7,37)\\(8,43)\\(9,49)\\(10,55)\\(11,61)\\ (13,68)\\(14,74)\\(15,80) \]


於是我們得到了五個數列\(\{b\}\),如下

\[\{b\}= \left \{ \begin{aligned} 2,5,7,10,13,15,18,20,&23,26,28,31,34,\dots (k=0)\\ 3,6,10,13,17,20,23,27,&30,34,37,40,44,\dots (k=1)\\ 4,8,12,17,21,25,30,34,&38,43,47,51,55,\dots (k=2)\\ 5,10,15,20,26,31,36,&41,47,52,57,62,\dots (k=3)\\ 6,12,18,24,30,37,43,&49,55,61,68,74,\dots (k=4)\\ \dots & \end{aligned} \right . \]

根據OEIS的輸出,得出(需要稍微轉化一下)

\[b_n= \left \{ \begin{aligned} \lfloor n\times \frac{3+\sqrt 5}{2} \rfloor&,\ k=0\\ \lfloor n\times \frac{4+\sqrt 8}{2} \rfloor&,\ k=1\\ \lfloor n\times \frac{5+\sqrt {13}}{2} \rfloor&,\ k=2\\ \lfloor n\times \frac{6+\sqrt {20}}{2} \rfloor&,\ k=3\\ \lfloor n\times \frac{7+\sqrt {29}}{2} \rfloor&,\ k=4\\ \dots & \end{aligned} \right . \]

容易發現規律,並得到通項表達如下

\[b_k=\lfloor n\times \frac{x+\sqrt y}{2} \rfloor\\ x=k+3\\ y=5+\frac{3+(k\times 2+1)}{2}\times k \]

\(y\)\({5,8,13,20,29,\dots}\),每項差\(3,5,7,9,\dots\),可以拆成\(5+\)等差數列求和)


得到了\(\{b\}\)數列的通項,那該怎么判斷對應的是哪一項,是不是必敗態呢

前面提到,我們能夠根據\(b-a\)的值獲得項數為\(\frac{b-a}{k+1}\)

根據項數代入公式即可求出必敗態這一項的\(b\)

判斷下兩個\(b\)是不是相同的就能確定是不是必敗態了



程序

(78ms/1000ms)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

void solve()
{
    ll a,b,k;
    scanf("%lld%lld%lld",&a,&b,&k);
    if(a>b)
        swap(a,b);
    if((b-a)%(k+1)==0)
    {
        int id=(b-a)/(k+1);
        ll x=3+k,y=(3+k*2+1)*k/2+5;
        ll tmp=(x+sqrt(y))*id/2.0;
        if(tmp==b)
            puts("0");
        else
            puts("1");
    }
    else
        puts("1");
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
        solve();
    return 0;
}



原版博弈

本題是威佐夫博弈(Wythoff's game)的變種

原版威佐夫博弈正是本題\(k=0\)時的情況

結論是:

假設兩堆石子數量為\((x,y),\ x\lt y\)

先手必敗,當且僅當滿足\(\frac{\sqrt 5+1}{2}(y-x)=x\)

(但我不會,還沒學)

所以想學的可以去別的地方學學

最后如果以通項方式解決,通項應該也是上面推出的那個




據說還有更簡單的遞推方法

我直接問號為敬?????

pic




最后這里放一下同校另外兩位大佬本題的博客

禾碩。

溢流眼淚



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM