zoukankan      html  css  js  c++  java
  • GMOJ 6829. 【2020.10.25提高组模拟】异或

    这是这场比赛第二水的一题,但我并没有切。

    题解:

    正解其实很简单,很容易可以发现一个性质,讲一个序列排序,xor值最小的值肯定出现在相邻两个数之间,
    证明:设a<b<c,那么我们只需要证明min(ab,bc)<a^c设到第t位开始第一次出现a,b,c在第t位上的值不同,有两种情况:
    1.(0,0,1) 此时ab<ac
    2. (0,1,1) 此时bc>ac
    综上所述,xor值最小的值肯定出现在相邻两个数之间。
    有了这个性质,我们就很容易可以想出正解:
    我们设f[i]表示以i结尾的序列个数,那么我们有f[i]=sigma(f[j] (a[i]^a[j]>=x) )+1。
    这个转移可以用trie来优化。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 500000
    #define K 63
    #define ll long long
    #define mo 998244353
    using namespace std;
    ll n,X,a[N],i,f[N],ans,num;
    struct trie{
    	ll sum,s[2];
    }tr[N*K];
    void insert(ll x,ll s,ll val,ll t){
    	if (t>K){
    		tr[x].sum+=val;
    		return;
    	}
    	ll p=s>>(K-t);
    	if (!tr[x].s[p&1]) tr[x].s[p&1]=++num;
    	insert(tr[x].s[p&1],s,val,t+1);
    	tr[x].sum=tr[tr[x].s[0]].sum+tr[tr[x].s[1]].sum;
    }
    ll get(ll x,ll s,ll t,ll X){
    	if (!x) return 0;
    	ll p=(s>>(K-t))&1,val=1ll<<(K-t),sum=0;
    	if (val>=X) sum+=tr[tr[x].s[1-p]].sum,sum%=mo;
    	if (val>X) sum+=get(tr[x].s[p],s,t+1,X),sum%=mo;
    	if (val<X) sum+=get(tr[x].s[1-p],s,t+1,X-val),sum%=mo;
    	return sum;
    }
    int main(){
    	freopen("xor.in","r",stdin);
    	freopen("xor.out","w",stdout);
    	scanf("%lld%lld",&n,&X);
    	for (i=1;i<=n;i++) scanf("%lld",&a[i]);
    	sort(a+1,a+n+1);
    	num=1;
    	for (i=1;i<=n;i++){
    		f[i]=1+get(1,a[i],1,X);
    		ans=(ans+f[i])%mo;
    		insert(1,a[i],f[i],1);
    	}
    	printf("%lld
    ",ans%mo);
    	return 0;
    }
    
  • 相关阅读:
    软解析和硬解析
    oracle存储过程常用技巧
    jquery-1.11.1.js
    JavaScript遍历table
    JavaScript向select下拉框中添加和删除元素
    glog
    DDL引发的对象invalidation
    模拟cursor pin S wait on X
    rsync 排除目录
    JavaScript解决select下拉框中的内容太长显示不全的问题
  • 原文地址:https://www.cnblogs.com/Mohogany/p/13887292.html
Copyright © 2011-2022 走看看