洛谷 P3235 [HNOI2014]江南樂 解題報告
阿新 • • 發佈:2018-12-19
P3235 [HNOI2014]江南樂
Description
兩人進行 T 輪遊戲,給定引數 F ,每輪給出 N 堆石子,先手和後手輪流選擇石子數大於等於 F 的一堆,將其分成任意(大於1)堆,使得這些堆中石子數最多的和最少的相差不超過1(即儘量均分)。求先手和後手誰必勝。
Input
輸入第一行包含兩個正整數T和F,分別表示遊戲組數與給定的數。
接下來T行,每行第一個數N表示該組遊戲初始狀態下有多少堆石子。之後N個正整數,表示這N堆石子分別有多少個。
Output
輸出一行,包含T個用空格隔開的0或1的數,其中0代表此時小A(後手)會勝利,而1代表小A的對手(先手)會勝利。
預處理每個單一遊戲的\(SG\)
小於\(F\)的置\(0\)必敗
大於\(F\)的列舉拆分的堆數,把分開的用\(SG\)定理求一個異或和。
發現可以用乘除分塊優化,對奇偶性相同的堆數當\(\lfloor\frac{n}{l}\rfloor\)一樣時,答案一樣。
預處理的複雜度\(O(n\sqrt n)\)
注意特判\(SG_1=0\)
直接\(SG\)定理回答詢問就可以了。
Code:
#include <cstdio> const int N=1e5+1; int SG[N],T,F,n,is[N]; int hxor(int x,int k) { if(k&1) return x; return 0; } int main() { scanf("%d%d",&T,&F); for(int i=F;i<N;i++) { for(int l=1,r;l<=i;l=r+1) { r=i/(i/l); is[hxor(SG[i/l],l-i%l)^hxor(SG[i/l+1],i%l)]=i; ++l; if(l<=r&&l<=i) is[hxor(SG[i/l],l-i%l)^hxor(SG[i/l+1],i%l)]=i; } for(int j=0;is[j]==i;j++) SG[i]=j+1; } SG[1]=0; while(T--) { scanf("%d",&n); int sg=0; for(int x,i=1;i<=n;i++) scanf("%d",&x),sg^=SG[x]; printf("%d ",sg>0); } return 0; }
2018.12.19