说在前面
并没有什么想说的,但是要保持格式=w=
题目
BZOJ3576传送门
看题可戳传送门
解法
把每堆石子看作一个游戏,然后多堆石子就是一个复合游戏
因为决策是一样的,不能操作的人输,所以是个公平组合游戏,用SG求解
分裂之后会有多堆石子,显然偶数堆等价于0堆,奇数堆等价于1堆
然后我们可以暴力求SG值,然而并过不去…
我们分析一下操作,把
a
a
石子分成 堆,每堆石子的个数至少为
⌊am⌋
⌊
a
m
⌋
,其中有
amodm
a
mod
m
堆会多一个石子。而
⌊am⌋
⌊
a
m
⌋
只有根号种取值,于是我们观察一下每一块能贡献的SG值(假设
⌊am⌋=⌊am+1⌋=⌊am+2⌋
⌊
a
m
⌋
=
⌊
a
m
+
1
⌋
=
⌊
a
m
+
2
⌋
)
如果分成
m+1
m
+
1
堆,会有
amodm+1
a
mod
m
+
1
堆多一个石子,此时奇偶性可能会改变
如果分成
m+2
m
+
2
堆,会有
amodm+2
a
mod
m
+
2
堆多一个石子,此时奇偶性和分成
m
m
<script type="math/tex" id="MathJax-Element-1555">m</script> 堆相同
所以每一块最多只会贡献两种SG值,分块的时候判断一下就好了
下面是代码
/**************************************************************
Problem: 3576
User: SasamiyaSaya
Language: C++
Result: Accepted
Time:9680 ms
Memory:1628 kb
****************************************************************/
#include <set>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
int T , F , N , maxH , SG[100005] ;
vector<int> stone[101] ;
struct MEX_data{
bool tb[100005] ;
int sta[100005] , topp ;
void init(){
memset( tb , 0 , sizeof( tb ) ) ;
topp = 0 ;
}
void clear(){
for( int i = 1 ; i <= topp ; i ++ ) tb[ sta[i] ] = false ;
topp = 0 ;
}
void Insert( int x ){
if( !tb[x] ) sta[++topp] = x , tb[x] = true ;
}
int find(){
for( int i = 0 ; ; i ++ )
if( !tb[i] ) return i ;
}
} ;
void preWork(){
MEX_data me ; me.init() ;
for( int i = 0 ; i < F ; i ++ ) SG[i] = 0 ;
for( int i = F ; i <= maxH ; i ++ ){
me.clear() ;
for( int M = 2 , ed ; M <= i ; M = ed + 1 ){
int k = i / M ;
ed = min( i , i / k ) ;
me.Insert( ( SG[k] * ( ( M - i % M )&1 ) ) ^ ( SG[k+1] * ( ( i % M )&1 ) ) ) ;
if( ed != M ){
M ++ ;
me.Insert( ( SG[k] * ( ( M - i % M )&1 ) ) ^ ( SG[k+1] * ( ( i % M )&1 ) ) ) ;
}
} SG[i] = me.find() ;
}
}
void solve(){
for( int i = 1 ; i <= T ; i ++ ){
int tmp = 0 ;
for( int siz = stone[i].size() , j = 0 ; j < siz ; j ++ )
tmp ^= SG[ stone[i][j] ] ;
printf( "%d " , tmp != 0 ) ;
}
}
int main(){
scanf( "%d%d" , &T , &F ) ;
for( int i = 1 ; i <= T ; i ++ ){
scanf( "%d" , &N ) ;
for( int j = 1 , t ; j <= N ; j ++ ){
scanf( "%d" , &t ) , stone[i].push_back( t ) ;
maxH = max( maxH , t ) ;
}
} preWork() ; solve() ;
}