zoukankan      html  css  js  c++  java
  • 洛谷 P4869 albus就是要第一个出场(线性基,异或值排名)

    传送门


    解题思路

    首先背过线性基的一个性质吧(因为我不会证明):
    线性基里的每一个异或值出现的次数相等,为 (2^{n-k})
    然后这题就变成统计某个数是第几大异或值了。
    分类讨论在归纳一下:
    假设询问的数字是q。当处理到第i位且q的这一位为1,且线性基这一位有数,则

    • 当前面位异或起来得到的这一位已经是1,则可以通过让其他数异或上a[i]来减小其他数,使其小于q。
    • 当前面位异或起来得到的这一位是0,则q必须要异或上a[i],但是别的数可以通过不异或a[i]使其小于q。

    综上,第i位对答案是否产生贡献只与q的第i位原来是否为1有关,与现在的状态无关。

    AC代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<vector>
    using namespace std;
    const int mod=10086;
    int n,x,a[35],cnt,q,ans[35];
    int ksm(int a,int b){
    	if(b==0) return 1;
    	if(b==1) return a;
    	int res=ksm(a,b/2);
    	if(b&1) return res*res%mod*a%mod;
    	return res*res%mod;
    }
    void insert(int x){
    	for(int i=30;i>=0;i--){
    		if(x&(1<<i)){
    			if(a[i]) x^=a[i];
    			else{
    				a[i]=x;
    				return;
    			}
    		}
    	}
    }
    int query(int x){
    	int res=0;
    	for(int i=30;i>=0;i--){
    		if((x&(1<<i))&&(a[i])){
    			res=(res+ksm(2,ans[i]))%mod;
    		}
    	}
    	return res;
    }
    int main(){
    	ios::sync_with_stdio(false);
    	cin>>n;
    	for(int i=1;i<=n;i++) cin>>x,insert(x);
    	for(int i=0;i<=30;i++) if(a[i]) ans[i]=cnt++;
    	cin>>q;
    	cout<<(ksm(2,n-cnt)*query(q)+1)%mod;
    	return 0;
    }
    
  • 相关阅读:
    Smarty数据、模版创建指引
    做了个google工具栏的饭否按钮
    php程序调试(远程调试,firephp)
    Linux shell编程与Makefile的一些记录(等待更新)
    My MSSQL Tips
    Castle.ActiveRecord中Save与SaveAndFlush的性能差别
    Linux Basic Approach (My Notes)
    去青城后山玩了一天
    Infopath 2007 使用实践(占位)
    Delphi 6
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/15476568.html
Copyright © 2011-2022 走看看