bzoj 3823: 定情信物

考虑每个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<algorithm>
#define ll long long
#define N 10000000
using namespace std;
ll rev[N];
int p;
void get_rev(int n)
{
int t=min(n,p-1);
rev[1]=1;
for (int i=2;i<=t;i++) rev[i]=rev[p%i]*(p-p/i)%p;
}
ll kpow(ll a,int b)
{
ll ans=1;
while (b)
{
if (b&1) ans=ans*a%p;
a=a*a%p; b>>=1;
}
return ans%p;
}
int main()
{
int n;
scanf("%d%d",&n,&p);
if (p==2) { printf("1\n"); return 0;}
get_rev(n);
ll ans=kpow(2,n); int 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*rev[tmp%p]%p;
ans=ans*rev[2]%p;
sum^=cnt?0:ans;
}
printf("%d\n",sum);
return 0;
}

HOME Back

你可能感兴趣的:(bzoj 3823: 定情信物)