zoukankan      html  css  js  c++  java
  • P4869 albus就是要第一个出场

    Description
    已知一个长度为(n)的正整数序列(A)(下标从1开始), 令 (S = { x | 1 leqslant x leqslant n }), (S)的幂集(2^S)定义为(S)所有子集构成的集合。定义映射$ f : 2^S o 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])

    (1leqslant Nleqslant 10^5),其余各数均不超过(10^9)


    首先求出序列(A)的线性基(V),如果序列(B)不存在重复元素,我们可以用二分找到(Q)的排名,如果存在重复元素,可以通过简单打表猜测,每个数都会出现同样的次数,次数为(2^{N-|V|})

    证明如下:

    记所有未加入线性基的元素集合为(C),则(|C|=N-|V|),我们选取其任意子集(S)

    根据线性基的性质可得,(forall xin S),存在唯一的(V)中元素的组合,使得其异或和为(x),即(V)存在唯一子集,使得其异或和为(x)

    那么对于(forall xin 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
    ");
    		return 0;
    	}
    	int Ans=(K-1)%P*mlt(2,n-tot)%P;
    	printf("%d
    ",(Ans+1)%P);
    	return 0;
    }
    
  • 相关阅读:
    定时任务 常用cron表达式
    链接UTF-8编码带BOM尾,访问出现404
    centos安装nginx
    cnetos安装jdk
    javaweb数据分页
    mvn clean install对idea中项目结构的影响
    spring使用servlet过滤器filter,进行登录校验
    docker安装mysql并修改远程登陆权限
    使用token令牌控制接口幂等性
    718.最长重复子数组
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/13690679.html
Copyright © 2011-2022 走看看