zoukankan      html  css  js  c++  java
  • hdu 5269 ZYB loves Xor I 分治 || Trie

    题目大意:

    长度为(n)的数组A。求对于所有数对((i,j)(i in [1,n],j in [1,n]))(lowbit(A_i xor A_j))之和.答案对998244353取模
    定义lowbit(0)=0

    题解:

    官方题解给出的Trie的做法...

    但是我有一个分治的做法:
    我们从低到高枚举二进制位:
    在每个二进制位枚举时,将所有的数按照这一二进制位为0或为1分成两组
    这样一共有两组的siz的乘积对的数在这一位上对答案做出贡献
    由于我们发现以后这两组数间不可能存在一组数再次对答案做出贡献
    所以我们可以直接将问题划分成两个不相干的子问题,递归求解.
    也是(O(nloga_i))

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    inline void read(int &x){
    	x=0;char ch;bool flag = false;
    	while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    	while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    const int maxn = 50010;
    const int mod = 998244353;
    int a[maxn],b[2][maxn],ans;
    void solve(int l,int r,int d){
    	if(d == 30 || l == r) return;
    	b[0][0] = b[1][0] = 0;
    	for(int i=l;i<=r;++i){
    		if((a[i]>>d)&1) b[1][++b[1][0]] = a[i];
    		else b[0][++b[0][0]] = a[i];
    	}
    	ans += ((1<<d)*(b[1][0]*b[0][0]%mod)) % mod;
    	if(ans >= mod) ans -= mod;
    	for(int i=1;i<=b[1][0];++i) a[l+i-1] = b[1][i];
    	for(int i=1;i<=b[0][0];++i) a[l+b[1][0]-1+i] = b[0][i];
    	int mid = l+b[1][0]-1;
    	if(l <= mid) solve(l,mid,d+1);
    	if(mid+1 <= r) solve(mid+1,r,d+1);
    }
    inline void work(int num){
    	int n;read(n);
    	for(int i=1;i<=n;++i) read(a[i]);
    	ans = 0;solve(1,n,0);
    	printf("Case #%d: %d
    ",num,ans<<1);
    }
    int main(){
    	int T;read(T);
    	for(int i=1;i<=T;++i) work(i);
    	getchar();getchar();
    	return 0;
    }
    
  • 相关阅读:
    Ubuntu下Nginx安装
    vi基本状态
    07. 背景图片距离
    06. 用css实现三角形
    Leetcode刷题 (二)
    Leetcode刷题 (一)
    目标检测中的AP计算
    python 引用(import)文件夹下的py文件
    git 上传和克隆文件
    Windows系统下Pytorch与python版本不匹配导致模块包导入错误
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6481012.html
Copyright © 2011-2022 走看看