Gym - 101848D:XOR(线性基 欧拉降幂)
题意:给定N,K,P,表示现在有一个集合{0, 1, ..., 2n - 1},问有多少个非空子集的异或和为K; 答案%P。(1 ≤ n ≤ 1018, 0 ≤ k ≤ min(2n - 1, 1018), 2 ≤ p ≤ 109, p is prime.)
思路:先抽离出一个线性基出来,然后非基部分乱选,然后基来调整。 而这里显然可以把二进制表示法下只有一个1的那些数抽离出来当基。
所以答案=2^(2^N-N)%P; 要注意的是:
1,K=0的时候有空集,所以减去。
2,欧拉降幂的时候2和P要互质,和当P=2时不满足,所以需要特判。
#include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) int qpow(ll a,ll x,int Mod) { int res=1; while(x){ if(x&1LL) res=1LL*res*a%Mod; a=1LL*a*a%Mod; x>>=1LL; } return res; } int main() { ll N,K,P,res=0; scanf("%lld%lld%lld",&N,&K,&P); if(P==2) { if(K==0) puts("1"); else puts("0"); return 0; } res=qpow(2,((qpow(2,N,P-1)-N%(P-1))%(P-1)+P-1)%(P-1),P)-(K==0); res=(res%P+P)%P; printf("%lld\n",res); return 0; }
It is your time to fight!