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;
}

  

 

posted @ 2014-12-27 21:45  Claris  阅读(371)  评论(0编辑  收藏  举报