挺裸的SG函数,和经典的Nim博弈差不多,就是从任选变成了只能选择因子个。打个表枚举一下因子就行了。至于SG函数的原理,就是SG定理,百度百科上讲的挺详细的,可以看一下。
还有知乎上的一个证明:链接
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+100;
int sg[N],pile[N],n;
vector<int > s;
int main(int argc, char const *argv[])
{
sg[0] = 0;
for(int i=1;i<N;++i){
s.clear();
for(int j=1;j*j<=i;++j){
if(i%j == 0){
s.push_back(sg[i-j]);
if(j*j != i) s.push_back(sg[i-i/j]);
}
}
for(int j=0;;++j){
if(count(s.begin(),s.end(),j) == 0){
sg[i] = j;
break;
}
}
//printf("%d %d\n", i,sg[i]);
}
scanf("%d",&n);
int sum = 0;
for(int i=0;i<n;++i){
scanf("%d",&pile[i]);
sum ^= sg[pile[i]];
}
int res = 0;
for(int i=0;i<n;++i){
sum ^= sg[pile[i]];
for(int j=1;j*j <= pile[i];++j){
if(pile[i]%j == 0){
if((sg[pile[i]-j]^sum) == 0) res++;
if(j*j != pile[i]){
if((sg[pile[i]-pile[i]/j]^sum) == 0) res++;
}
}
}
sum ^= sg[pile[i]];
}
printf("%d\n", res);
return 0;
}