传送门
题解:
很显然 1 1 1就是这个游戏的终止位置,而每个石头走到 1 1 1的步数是确定的。
很显然这是一个阶梯博弈,一个位置的奇偶性就是所有质因子的指数之和的奇偶性。
显然总的合法操作个数就是 ∑ i = 1 n a i b i \sum_{i=1}^{n}a_ib_i ∑i=1naibi,其中 b i b_i bi表示 i i i的不同质因子个数。
那么现在考虑每个奇位置把石头挪开或者从偶位置挪过来。
假设 i i i是一个奇位置,所有奇位置的异或和为 X o r Xor Xor,我们现在需要把 i i i上的数变成 X o r ⊕ a i Xor\oplus a_i Xor⊕ai才能使得下一个局面先手必败,设 n e e d = X o r ⊕ a i need=Xor\oplus a_i need=Xor⊕ai。
如果 n e e d = a i need=a_i need=ai,显然我们不能动,怎么动下一个局面都是先手必胜。
如果 n e e d < a i need<a_i need<ai,显然只需要把 i i i位置上多的转移到下方的偶位置就行了,方案数为 b i b_i bi。
如果 n e e d > a i need>a_i need>ai,枚举所有能够直接转移到 i i i的偶位置,看这个位置上有没有足够的石头来把 a i a_i ai加到 n e e d need need就行了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<22|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>
inline T get(){
char c;
while(!isdigit(c=gc()));T num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline int getint(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
cs int mod=998244353;
inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline int power(int a,int b,int res=1){
for(;b;b>>=1,a=mul(a,a))(b&1)&&(res=mul(res,a));
return res;
}
inline void Inc(int &a,int b){(a+=b)>=mod&&(a-=mod);}
inline void Dec(int &a,int b){(a-=b)<0&&(a+=mod);}
cs int N=1e6+7;
int b[N],c[N];
bool mark[N];
int prime[N],pcnt;
inline void linear_sieves(int len){
for(int re i=2;i<=len;++i){
if(!mark[i])prime[++pcnt]=i,b[i]=c[i]=1;
for(int re j=1;i*prime[j]<=len;++j){
mark[i*prime[j]]=true;
c[i*prime[j]]=c[i]^1;
if(i%prime[j])b[i*prime[j]]=b[i]+1;
else {
b[i*prime[j]]=b[i];
break;
}
}
}
}
int n,a[N];
int Xor,all,ok;
signed main(){
#ifdef zxyoi
freopen("stone.in","r",stdin);
#endif
n=getint();linear_sieves(n);
for(int re i=1;i<=n;++i){
a[i]=getint();
if(c[i])Xor^=a[i];
Inc(all,mul(a[i],b[i]));
}
for(int re i=1;i<=n;++i){
if(c[i]){
int need=Xor^a[i];
if(need==a[i])continue;
if(need<a[i])Inc(ok,b[i]);
else {
need-=a[i];
for(int re j=1;j<=pcnt&&i*prime[j]<=n;++j)
if(a[i*prime[j]]>=need)Inc(ok,1);
}
}
}
cout<<power(all,mod-2,ok)<<"\n";
return 0;
}