XSY3949 取石子遊戲(博弈,線段樹)

2021-10-25 16:49:12 字數 2112 閱讀 9354

取石子遊戲

我們把乙個有 n

nn 個石子, alice 每次能拿 a

aa 個, bob 每次能拿 b

bb 個的堆稱為狀態 (n,

a,b)

(n,a,b)

(n,a,b

)。石子數太大的時候不利於分析,嘗試簡化一下:

可以證明狀態 (n,

a,b)

(n,a,b)

(n,a,b

) 的結果同 (nm

od(a

+b),

a,b)

(n\bmod (a+b),a,b)

(nmod(

a+b)

,a,b

) 狀態的結果相同。

所以我們只需對每乙個 n←n

mod(

a+b)

n\gets n\bmod(a+b)

n←nmod

(a+b

),然後只考慮 n

bn

nb 的情況。

注意兩人此時的步數是相同的,所以他們各自的最優策略是最大化「他們自己接下來走的步數-另乙個人接下來走的步數」,不妨設這個值對於兩人而言是 sa,

sb

s_a,s_b

sa​,sb

​。對於每個堆分類討論:

所以三種情況我們都處理完了。

**如下:

#include

#define n 200010

#define lc (k<<1)

#define rc (k<<1|1)

#define int long long

using

namespace std;

inline

intread()

while

(ch>=

'0'&&ch<=

'9')

return x*f;

}int n,x[n]

,a[n]

,b[n]

;int suma[n]

,sumb[n]

;int tot,p[n]

,q[n]

,rk[n]

;int s[n]

,pa[n]

,pb[n]

;int sum[n<<2]

[2];

bool size[n<<2]

;bool

cmp(

int a,

int b)

voidup(

int k)

else

}void

update

(int k,

int l,

int r,

int x,

int y)

int mid=

(l+r)

>>1;

if(x<=mid)

update

(lc,l,mid,x,y)

;else

update

(rc,mid+

1,r,x,y);up

(k);

}signed

main()

if(x[i]

) p[i]

=x[i]

/a[i]

+x[i]

/b[i]-2

,q[++tot]

=i; s[i]

+=p[i]

,pa[i]

+=x[i]

/a[i]-1

,pb[i]

+=x[i]

/b[i]-1

;}sort

(q+1

,q+tot+

1,cmp)

;for

(int i=

1;i<=tot;i++

) rk[q[i]

]=i;

bool tag=0;

for(

int i=

1;i<=n;i++

)return0;

}/*43 2 4

4 5 2

1 1 2

5 3 4

*/

博弈 取石子遊戲

兩堆石子,數量任意,可以不同。遊戲開始由兩個人輪流取石子。遊戲規定,每次有兩種不同的取法,一是可以在任意的一堆中取走任意多的石子 二是可以在兩堆中同時取走相同數量的石子。最後把石子全部取完者為勝者。現在給出初始的兩堆石子的數目,如果輪到你先取,假設雙方都採取最好的策略,問最後你是勝者還是敗者。inp...

簡單取石子遊戲 博弈

很坑爹的小遊戲,至於怎麼坑爹,嘎嘎 自己研究去吧 include include include include includeusing namespace std void loc int x,int y 定位游標 void welcome 建立歡迎介面 void buildmap 建立介面 v...

題解 取石子遊戲(博弈)

題目描述 一天小明和小紅在玩取石子遊戲,遊戲規則是這樣的 1 本遊戲是乙個二人遊戲 2 有一堆石子,共有n個 3 兩人輪流進行 4 每走一步可以取走1 m個石子 5 最先取光石子的一方為勝。如果遊戲的雙方使用的都是最優策略,請輸出哪個人能贏。輸入輸入的第一行是乙個正整數c c 100 表示有c組測試...