都说程序员找不到妹子,可是无人知晓,三生石上竟然还刻着属于小 E 的一笔。
那一天,小 E 穷尽毕生的积蓄,赠与了妹子一个非同寻常的定情信物。那是一个小
小的正方体,但透过它,可以看到过去,可以洞彻天机。
这份信物仿佛一只深邃的眼。当看透它看似简单的外表后,深邃的内心却最是可以
叩击人的灵魂的。不出所料,妹子果然被这个信物超越空间的美所吸引。
“易有太极,是生两仪,两仪生四象,四象生八卦。,八卦定吉凶,吉凶生大业。”
这句箴言在其上得到了完美的诠释。
是的,这正是一个超正方体。
小 E 告诉妹子,他的情意也如这份信物一样深厚。现在妹子想知道,小 E 对她的情
意究竟有几分?
我们知道,点动成线,线动成面,面动成体......即 n 维超立方体可看作由 n-1 维超
立方体沿垂直于它的所有的棱的方向平移得到的立体图形。
我们可以将点看作 0 维超立方体,将直线看作 1 维超立方体,将正方形看作 2 维超
立方体......依此类推。
任何一个 n 维超立方体(n>0)都是由低维的超立方体元素组成的:它的 n-1 维表面
是 n-1 维的超立方体,它的 n-2 维边缘是 n-2 维的超立方体,它的 n-3 维元素是 n-3 维的
超立方体......
小 E 对妹子的情意即为在他的定情信物——K 维超立方体中,含有每一维的元素个
数。由于元素个数可能较大,只需要输出它所包含的每一维元素个数模 P 后的异或和。
一个非负整数,表示小 E 的定情信物所包含的每一维元素个数模 P 后的异或和。注
意:异或和可能会大于 P。
对于 100%的数据,N≤10^7,P 为 10^9 内的素数。
/*
考虑每个n维超立方体的k维元素的“对角线”向量就是从n维中选出k维,每一维为+1或-1,答案就是C(n,k)*2^k,在预处理出逆元之后可以O(n)。
但是由于p可以<n,所以可能要求(b*p)^(-1),这个是没有逆元的,所以维护cnt表示当前答案p有几个,还要注意逆元是rev[tmp%p]。
*/
#include<cstdio>
#include<iostream>
#define lon long long
#define N 10000010
using namespace std;
int n,p;lon inv[N];
void get_inv(){
int t=min(n,p-1);
inv[1]=1;
for(int i=2;i<=t;i++)
inv[i]=inv[p%i]*(p-p/i)%p;
}
lon poww(lon a,int b){
lon ans=1;
while(b){
if(b&1) ans=ans*a%p;
a=a*a%p;b>>=1;
}
return ans%p;
}
int main(){
scanf("%d%d",&n,&p);
if(p==2){printf("1\n");return 0;}
get_inv();
lon ans=poww(2,n);lon sum=ans,cnt=0;
for(int i=1;i<=n;i++){
int tmp=n-i+1;
while(tmp%p==0) cnt++,tmp/=p;
ans=ans*tmp%p;
tmp=i;
while(tmp%p==0) cnt--,tmp/=p;
ans=ans*inv[tmp%p]%p;
ans=ans*inv[2]%p;
sum^=cnt?0:ans;
}
printf("%d\n",sum);
return 0;
}