BZOJ3823 : 定情信物
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; }