n维超立方体有$2^{n-i}C_n^i$个i维元素,于是$O(n)$预处理出1到n的逆元,再$O(n)$计算即可。
注意Trick:P可能小于n,所以要将数字表示成$a\times P^b$的形式。
#include<cstdio>
#define N 10000001
typedef long long ll;
int n,i,j,P,r[N],a[N];ll ans,x,y;char c[N];
int main(){
scanf("%d%d",&n,&P);
if(P==2)return puts("1"),0;
for(r[1]=a[1]=1,i=2;i<=n;i++)if(i%P==0){
for(j=i;j%P==0;j/=P)c[i]++;
r[i]=r[a[i]=j];
}else{
a[i]=i;
if(i>=P)r[i]=r[i%P];else{
r[i]=-(ll)r[P%i]*(P/i)%P;
while(r[i]<0)r[i]+=P;
}
}
for(ans=x=i=1;i<=n;i++){
x=x*a[n-i+1]%P*2%P*r[i]%P,y+=c[n-i+1]-c[i];
if(!y)ans^=x;
}
return printf("%lld",ans),0;
}