• 【ybtoj】【字典树】lowbit求和


    题意

    image

    题解

    首先考虑 lowbit 有什么特性。
    lowbit(x)表示 (x) 的二进制最低位的 (1) 的所对应的值。
    那么对于两个数的异或,从低到高找到二进制第一位不同的位置即可知道 lowbit 的答案。
    所以考虑先把所有数插入 Trie 树中,记录每一个位置的数字有多少个。
    统计答案的时候把每一个数在 Trie 树上跑一遍,每次找到 Trie 树上与当前位置不同的一边子树内的答案已经确定(即已经找到那些数最低位的 (1)),继续走与当前位置相同的一边子树。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int INF = 0x3f3f3f3f,N = 1e5+10;
    const ll mod = 199907210507;
    inline ll read()
    {
    	ll ret=0;char ch=' ',c=getchar();
    	while(!(c>='0'&&c<='9')) ch=c,c=getchar();
    	while(c>='0'&&c<='9') ret=(ret<<1)+(ret<<3)+c-'0',c=getchar();
    	return ch=='-'?-ret:ret;
    }
    int n,tot=1;
    ll a[N*60],num[N*60],trie[N*60][2]; 
    inline void insert(int id)
    {
    	int p=1;
    	for(int i=0;i<=61;i++)
    	{
    		int ch=(a[id]>>i)&1;
    		if(!trie[p][ch]) trie[p][ch]=++tot;
    		p=trie[p][ch];
    		num[p]++;
    	}
    }
    inline ll lowbit(int id)
    {
    	int p=1;
    	ll ret=0;
    	for(int i=0;i<=61;i++) 
    	{
    		int ch=(a[id]>>i)&1;
    		if(trie[p][ch^1]) (ret+=num[trie[p][ch^1]]%mod*(1ll<<i)%mod)%=mod;
    		p=trie[p][ch];
    	}
    	return ret;
    }
    int main()
    {	
    	n=read();
    	for(int i=1;i<=n;i++) 
    	{
    		a[i]=read();
    		insert(i);
    	}
    	ll ans=0;
    	for(int i=1;i<=n;i++) ans+=lowbit(i),ans%=mod;
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    支付清结算之基本概念和入门
    支付清结算之账户和账务处理
    支付系统设计:支付系统的账户模型(一)
    Docker架构和原理
    Docker容器的原理、特征、基本架构、与应用场景
    Docker的用途与原理
    Random函数的安全性问题与SecureRandom
    nginx配置https
    CentOS Docker 安装
    Nginx能做什么
  • 原文地址:https://www.cnblogs.com/conprour/p/15315724.html
Copyright © 2020-2023  润新知