首先需要预处理出x个石子能够进行的操作数,存到链表e[x]里面该步骤为n
对每一堆石子求sg函数,对每一堆石子枚举考虑该步骤能否是sg的异或为0,可以则方案数加一
注意:在分解操作中两个约数相同要排除,该操作不会影响sg,但会是方案数重复计算
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int f[N];
vector<int> e[N];
void divide(int x)
{
for(int i=1;i*i<=x;++i)
{
if(x%i==0)
{
e[x].push_back(i);
//e[i]重复放元素不会影响sg的值,但在对步骤的统计中会重复计算方案数
if(i!=x/i)
e[x].push_back(x/i);
}
}
}
int sg(int x)
{
if(~f[x]) return f[x];
set<int> S;
for(auto p:e[x])
{
S.insert(sg(x-p));
}
for(int i=0;;++i) if(!S.count(i)) return f[x]=i;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
memset(f,-1,sizeof f);
f[0]=0;
int n; cin>>n;
for(int i=1;i<=1e5;++i) divide(i);
vector<int> a(n);
int ans = 0;
for(int i=0;i<n;++i)
{
cin>>a[i];
ans^=sg(a[i]);
}
//cout<<ans<<'\n';
int tmp = 0;
long long res = 0;
for(int i=0;i<n;++i)
{
tmp = ans^sg(a[i]);
for(auto p:e[a[i]])
{
if((tmp^sg(a[i]-p))==0) res++;
}
}
cout<<res<<"\n";
}