雅禮集訓 1 2 取石子遊戲

2021-08-14 17:31:51 字數 2790 閱讀 9427

【題目描述】

有 n 堆石子,第 i 堆有 xi 個。

alice 和 bob 輪流取石子(先後手未定),alice 每次從一堆中取走 a 個,bob

每次從一堆中取走 b 個,無法操作者輸。

不難發現只會有四種情況:alice 必勝;bob 必勝;先手必勝;後手必勝。

你需要選定若干堆石子(共有 2^n 種方案),alice 和 bob 只能在你選出的堆

中取,問以上四種情況對應的方案數。

【輸入資料】

第一行三個整數 n,a,b,第二行 n 個整數 x1~xn。

【輸出資料】

一行四個整數,分別表示 alice 必勝、bob 必勝、先手必勝和後手必勝的方

案數,對 10^9+7 取模。

【樣例輸入】

2 2 3

2 3【樣例輸出】

2 0 1 1

【樣例解釋】

選定空集時後手必勝,選定時 alice 必勝,選定時先手必勝,選定時 alice

必勝。【資料範圍】

對於 10%的資料,n,xi<=5。

對於 50%的資料,n<=20。

對於另外 10%的資料,a=b。

對於又另外 20%的資料,a=1。

對於 100%的資料,1<=n<=100000,1<=a,b,xi<=10^9。

首先我們可以把每堆石子的個數mod(a+b)

這是從博弈學的平衡性(我自己取的名)入手的

下面是個人見解,正確性unknown

首先,這樣想一場遊戲,只有一堆石子

你取了a個,對方緊跟著你在同一堆取了b個,

一輪減少(a+b)個 ,其實無論經過多少輪結果都是一樣的。

該輸的照樣輸,該贏的照樣贏

那麼就把個數mod(a+b)不就好了?

如果有多堆的話,一人突然對另外一堆來操作

這時,另一人會緊跟前一人去同樣的堆操作

且在前一人重新對原來的堆操作之前,也不對前一堆操作

這樣,其實第一人只是將操作推後了而已,他還是要操作的。

那麼,為啥另一人會跟著呢?

因為前一人換堆肯定是因為他不換就會輸

後一人就會贏,所以後一人這樣就可以將前一人鎖定在必輸的情形,這是出於最佳策略

就像那個多個遊戲的和什麼什麼的。。。。。

然後對於所有的堆分類討論即可,

::stone:

不妨假設a每堆石子先對a+b取模,然後可以分為4種:

(1) xi(2) a<=xi,只要存在則a必勝。

(3) b<=xi<2a,只和奇偶性有關。

(4) 2a<=xi,存在至少2個則a必勝,存在1個且(3)為偶數則先手必勝,存在1個且(3)為奇數則a必勝,不存在且(3)為奇數則先手必勝,不存在且(3)為偶數則後手必勝。

注意,在n個物品中選出奇數個物品的方案數為2^(n-1)

(或偶數個物品)

看看楊輝三角就知道 了。

另外這個題將無石子歸為後手贏,相當於強行定義c(0,0)=1,這不僅讓楊輝三角失去了樸素的美感,還讓**擠滿了醜惡的三目運算子。

accode:

//神之技巧:σc(n,k)=2^(n-1) 其中k為都奇數,或都為偶數,可以從楊輝三角上直觀的證明

/*0:無關

1:b>=u>=a 有則a必勝 因為a可以把這堆屯著,b管不著

然後是重要的兩點

i:如果2*a>b

那麼一堆石子滿足b<=u<2*a

雙方只要有乙個人拿了一次,就會使它廢為第0類,成為爭奪的重點,有奇數個則先手贏,否則後手贏

一堆石子滿足 u>=2*a>b

那麼a只要拿一次就可以把它轉化為1然後勝利

所以b的唯一機會就是先手(搞掉唯一的一堆),

所以這樣的石子有兩堆則a必贏

有一堆則b可能贏(把這堆破壞會浪費b的先手條件,看奇偶)。

無則看奇偶

ii:如果2*a<=b

那麼a<=2*a<=b

無異於1

u>=b時看奇偶

*/#include#include#include#include#define mod 1000000007

#define maxn 100005

#define ll long long

using namespace std;

ll n,a,b;

bool rev;

ll pow(int base,int k)

int main(),ans[5]={};

for(int i=1;i<=n;i++)

ll inc=pow(2,cnt[0]);//最後計算

ans[0]=((pow(2,cnt[1])-1)*pow(2,cnt[2]+cnt[3])%mod+(pow(2,cnt[3])-cnt[3]-1)*pow(2,cnt[2])%mod+cnt[3]*(cnt[2]?pow(2,cnt[2]-1):0)%mod)%mod;

//ans[1]=0;

ans[2]=((cnt[2]?pow(2,cnt[2]-1):0)+(cnt[2]?pow(2,cnt[2]-1):1)*cnt[3]%mod)%mod;

ans[3]=(cnt[2]?pow(2,cnt[2]-1):1);

for(int i=0;i<4;i++)

ans[i]=(ans[i]*inc)%mod,

ans[i]=(ans[i]+mod)%mod;

if(rev) swap(ans[0],ans[1]);

printf("%lld %lld %lld %lld\n",ans[0],ans[1],ans[2],ans[3]);

}

雅禮國慶集訓

灑落君臣契,飛騰戰伐名。杜甫 公安縣懷古 noip 前的乙個月。這浸滿熱血的虔信,真的會化作墓碑嗎?或許明日我們不再是戰友,但人生終將有無數個此時。define f z,u,v for int z u des z v z des z z struct bnd struct tup template ...

雅禮集訓 2017 價

傳送門 乙個不太顯然的最小割做法。我們這麼連邊 源點向藥物連 infty p i 容量的邊,藥物向它對應的藥材連 infty 容量的邊,藥材向匯點連 infty 容量的邊。用源點的流量減去最小割,再負回來就可以求出答案了。怎麼理解呢?割掉一條邊表示不選其對應的藥物或藥材,我們發現最後的方案一定是完美...

雅禮集訓 2017 Day2 線段遊戲

記憶體限制 256 mib 時間限制 1000 ms 標準輸入輸出 題目型別 傳統 評測方式 special judge 上傳者 匿名 題目描述 給出若干條線段,用 x1,y2 x2,y2 表示其兩端點座標,現在要求支援兩種操作 輸入格式 第一行兩個正整數 n m 為初始的線段個數和操作個數。接下來...