zoukankan      html  css  js  c++  java
  • BZOJ.2844.albus就是要第一个出场(线性基)

    题目链接

    (Description)

    给定一个集合A,将 所有子集中的所有数的异或和(包括空集) 从小到大排序,求一个数K在其中的排名(保证出现)。

    (Solution)

    构造出线性基,然后只保留线性基中存在数的位。
    类似数位DP,对K二进制分解,如果K的当前位为1,那么先不选这一位,则后面的(i-1)位任意选择都比K小,且有(2^i)种方案(包括空集),加给答案。
    但是在不去重的情况下,每个数可能出现多次。如果线性基的大小为(size),原集合大小为(n),那么线性基中 每个数都出现了(2^{n-size})次。
    因为存在(n-size)个数,它们在线性基中可以唯一表示出来。那么对于一个数(x),从这(n-size)个数中任选一些Xor,总有唯一的方案使得在线性基中再异或后仍为(x)
    所以答案再乘上(2^{n-size})就行了。
    注意对K分解是在线性基上存在数的对应位上分解。

    //1016kb	160ms
    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    //#define gc() getchar()
    #define MAXIN 200000
    #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
    #define Bit 30
    #define mod 10086
    #define Double(x) ((x+=mod)>=mod)&&(x-=mod)
    
    int n,size,base[36],cnt,A[36];
    char IN[MAXIN],*SS=IN,*TT=IN;
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now;
    }
    inline int FP(int x,int k)
    {
    	int t=1;
    	for(; k; k>>=1, x=x*x%mod)
    		if(k&1) t=t*x%mod;
    	return t;
    }
    inline void Insert(int x)
    {
    	for(int i=Bit; ~i; --i)
    		if(x>>i & 1)
    			if(base[i]) x^=base[i];
    			else {base[i]=x, ++size; break;}
    }
    
    int main()
    {
    	n=read();
    	for(int i=1; i<=n; ++i) Insert(read());
    	int K=read();
    	for(int i=0; i<=Bit; ++i) if(base[i]) A[cnt++]=i;
    	int ans=0;
    	for(int i=0; i<cnt; ++i)
    		if(K>>A[i] & 1) ans+=1<<i;
    	printf("%d
    ",(ans%mod*FP(2,n-size)%mod+1)%mod);//排名加1啊→_→
    
    	return 0;
    }
    
  • 相关阅读:
    Kafka 生产者 自定义分区策略
    同步互斥
    poj 1562 Oil Deposits(dfs)
    poj 2386 Lake Counting(dfs)
    poj 1915 KnightMoves(bfs)
    poj 1664 放苹果(dfs)
    poj 1543 Perfect Cubes (暴搜)
    poj 1166 The Clocks (暴搜)
    poj 3126 Prime Path(bfs)
    处理机调度
  • 原文地址:https://www.cnblogs.com/SovietPower/p/9292621.html
Copyright © 2011-2022 走看看