如果用f[i][j]表示i维空间里的j维元素有多少个,有公式 f[i][j] = C(i,j) * 2^(i-j)
……看题解似乎都是找规律的啊……sro mhy orz
考虑j维向量的方向有C(i,j)个,对于每个方向的向量,可以放置的位置的数量 显然就是剩下的几维随便填的方案数,2^(i-j)
毛神他们加的数据……大概就是当n>p的时候……p的倍数没有逆元这样的毒瘤数据,稍微记一下有多少个p就好了
……
哦还有线性地求1~n的逆元……私觉得Miskcoo大爷讲得很稳
传送门:http://blog.miskcoo.com/2014/09/linear-find-all-invert
代码:
#include<bits/stdc++.h>
#define MAXN 10000007
using namespace std; int n,p;
int inv[MAXN];
int cf2[MAXN];
int rec_fac = 1,rec_fac_p;
inline void init(){
inv[1] = 1 ;
for(register int i=2;i<=min(n,p-1);++i) inv[i] = 1ll * (p - p/i) * inv[p%i] % p;
cf2[0] = 1 ;
for(register int i=1;i<=n;++i) cf2[i] = cf2[i-1] * 2 % p;
}
int ans = 0;
inline void work(){
int now = 1;
ans = cf2[n] ^ 1;
for(register int i = 1; i<n;++i,now = now*2 % p){
int k = n - i + 1;
while(!(k%p)) ++rec_fac_p,k/=p;
rec_fac = 1ll * rec_fac * k % p;
k = i ;
while(!(k%p)) --rec_fac_p,k/=p;
rec_fac = 1ll * rec_fac * inv[k%p] % p;
if(!rec_fac_p)
ans ^= (int)(1ll * rec_fac * cf2[n-i] % p);
// printf("%d\n",ans);
}
printf("%d",ans);
}
int main(){
scanf("%d%d",&n,&p);
init();
work();
return 0;
}