hdu5269ZYB loves Xor I

这个题还挺有意思的,虽然做法还是很显然的,但是还是值得写篇博客


标程是字典树,看起来比较蛋疼


直接分治就好了,


排序之后,使得ai不被排在它后面的管控,也就是lowbit(a[i])<=lowbit(a[j]),i<j


然后接下来分治,每次把区间分成两半,使得前面一半管控后面一半,一边拆一边算ans


这里,我直接写了一发dfs,很显然递归深度最多也就logA,放心跑


最后打出ans即可


排序的复杂度是nlognlogA


分治就是nlogA


时间主要花在排序上,事实上,排序的实际时间应该更好,所以跟标程的nlogA并没有太大区别


这里因为hd服务器的原因,交g++会蜜汁re,c++很快就过了


Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 188    Accepted Submission(s): 103


Problem Description
Memphis loves xor very musch.Now he gets an array A.The length of A is n.Now he wants to know the sum of all (lowbit( Ai  xor  Aj ))  (i,j[1,n])
We define that lowbit(x)= 2k ,k is the smallest integer satisfied (( x  and  2k )>0)
Specially,lowbit(0)=0
Because the ans may be too big.You just need to output  ans  mod 998244353
 

Input
Multiple test cases, the first line contains an integer T(no more than 10), indicating the number of cases. Each test case contains two lines
The first line has an integer  n
The second line has  n  integers  A1 , A2 .... An
n[1,5104] Ai[0,229]
 

Output
For each case, the output should occupies exactly one line. The output format is Case #x: ans, here x is the data number begins at 1.
 

Sample Input
  
  
2 5 4 0 2 7 0 5 2 6 5 4 0
 

Sample Output
  
  
Case #1: 36 Case #2: 40
 

Source

#include<map>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<climits>
#include<list>
#include<iomanip>
#include<stack>
#include<set>
using namespace std;
typedef long long ll;
const int mod=998244353;
int lowbit(int x)
{
	return x&-x;
}
int a[50010],n,ans;
void dfs(int l,int r)
{
	if(l==r||a[l]==0)
		return;
	for(int i=l;i<=r;i++)
	{
		int t=lowbit(a[i]);
		a[i]-=t;
		if(i==r)
			dfs(l,r);
		else if(t!=lowbit(a[i+1]))
		{
			ans=(ans+ll(i-l+1)*(r-i)*t*2%mod)%mod;
			dfs(l,i);
			dfs(i+1,r);
			break;
		}
	}
}
bool cmp(int one,int two)
{
	while(1)
	{
		int t1=lowbit(one),t2=lowbit(two);
		if(t2==0)
			return 1;
		else if(t1==0)
			return 0;
		if(t1<t2)
			return 1;
		else if(t1>t2)
			return 0;
		one-=t1;
		two-=t2;
	}
}
int main()
{
	int T;
	scanf("%d",&T);
	for(int cs=1;cs<=T;cs++)
	{
		int n;
		scanf("%d",&n);
		for(int i=0;i<n;i++)
			scanf("%d",a+i);
		ans=0;
		sort(a,a+n,cmp);
		dfs(0,n-1);
		printf("Case #%d: %d\n",cs,ans);
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值