P4869 albus就是要第一个出场
Description
已知一个长度为\(n\)的正整数序列\(A\)(下标从1开始), 令 \(S = \{ x | 1 \leqslant x \leqslant n \}\), \(S\)的幂集\(2^S\)定义为\(S\)所有子集构成的集合。定义映射$ f : 2^S \to Z,f(\emptyset) = 0,f(T) = \mathrm{XOR}{A_t}, (t \in T)$ 。
现在albus把\(2^S\)中每个集合的f值计算出来, 从小到大排成一行, 记为序列\(B\)(下标从1开始)。
给定一个数, 那么这个数在序列\(B\)中第1次出现时的下标是多少呢?
Input
第一行一个数\(n\), 为序列\(A\)的长度。接下来一行\(n\)个数, 为序列\(A\), 用空格隔开。最后一个数\(Q\), 为给定的数。
Output
共一行,一个整数,为\(Q\)在序列\(B\)中第一次出现时的下标模\(10086\)的值。
Sample Input
3
1 2 3
1
Sample Output
3
HINT
记\(\otimes\)为xor运算
\(N = 3, A = [1,2,3]\)
\(S = {1, 2, 3}\)
\(2^S = \{\emptyset, \{1\}, \{2\}, \{3\}, \{1, 2\}, \{1, 3\}, \{2, 3\}, \{1, 2, 3\}\}\)
\(f(\emptyset) = 0\)
\(f(\{1\}) = 1\)
\(f(\{2\}) = 2\)
\(f(\{3\}) = 3\)
\(f(\{1, 2\}) = 1 \otimes 2 = 3\)
\(f(\{1, 3\}) = 1 \otimes 3 = 2\)
\(f(\{2, 3\}) = 2 \otimes 3 = 1\)
\(f(\{1, 2, 3\}) = 1 \otimes 2 \otimes 3 = 0\)
所以 \(B=[0,0,1,1,2,2,3,3]\)
\(1\leqslant N\leqslant 10^5\),其余各数均不超过\(10^9\)
首先求出序列\(A\)的线性基\(V\),如果序列\(B\)不存在重复元素,我们可以用二分找到\(Q\)的排名,如果存在重复元素,可以通过简单打表猜测,每个数都会出现同样的次数,次数为\(2^{N-|V|}\)
证明如下:
记所有未加入线性基的元素集合为\(C\),则\(|C|=N-|V|\),我们选取其任意子集\(S\)
根据线性基的性质可得,\(\forall x\in S\),存在唯一的\(V\)中元素的组合,使得其异或和为\(x\),即\(V\)存在唯一子集,使得其异或和为\(x\)
那么对于\(\forall x\in B\),我们都可以找到\(2^{|C|}\)种方案,证毕
然后记得特判一下0的位置就好
/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
static char buf[1000000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>inline T frd(T x){
int f=1; char ch=gc();
for (;ch<'0'||ch>'9';ch=gc()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<1)+(x<<3)+ch-'0';
return x*f;
}
template<typename T>inline T read(T x){
int f=1;char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
return x*f;
}
inline void print(int x){
if (x<0) putchar('-'),x=-x;
if (x>9) print(x/10);
putchar(x%10+'0');
}
template<typename T>inline T min(T x,T y){return x<y?x:y;}
template<typename T>inline T max(T x,T y){return x>y?x:y;}
template<typename T>inline T swap(T &x,T &y){T t=x; x=y,y=t;}
const int N=30,P=10086;
int A[N+10],tot;
int Add(int x){
for (int i=N;~i;i--){
if (x&(1<<i)){
if (A[i]) x^=A[i];
else{
A[i]=x;
return 1;
}
}
}
return 0;
}
int Find(int K){
int Ans=0;
for (int i=0;i<=N;i++){
if (A[i]){
if (K&1) Ans^=A[i];
K>>=1;
}
}
return Ans;
}
int Binary_search(int x){
int l=1,r=(1<<tot)-1;
while (l<r){
int mid=(l+r)>>1;
Find(mid)>=x?r=mid:l=mid+1;
}
return l+1;
}
int mlt(int a,int b){
int Ans=1;
for (;b;b>>=1,a=a*a%P) if (b&1) Ans=Ans*a%P;
return Ans;
}
int main(){
int n=read(0);
for (int i=1;i<=n;i++) tot+=Add(read(0));
for (int i=N;~i;i--)
for (int j=i;j;j--)
if (A[i]&(1<<(j-1)))
A[i]^=A[j-1];
int x=read(0),K=Binary_search(x);
if (!x){
printf("1\n");
return 0;
}
int Ans=(K-1)%P*mlt(2,n-tot)%P;
printf("%d\n",(Ans+1)%P);
return 0;
}