牛客月赛25-异或和之和-(位运算+组合数)

J

题意:
就是给你n个数,一共去C(n,3)个三元组,计算axorbxorc,然后把所有的值加起来,问你是多少,对mod取余。

思考:
位运算的题一直是我的弱项,其实也做过不少了,无非就是按每一位去考虑。刚开始看到这题感觉没想法,去做别的了,然后最后再来看这个题,还是没想法。又自己问了问自己,如果是两元组呢,你怎么做,想到这我就想到了,按每一位看,选一个是1的选一个是0的异或起来才有贡献,想到这就明白了。对于三元组,就是选两个0和一个1,还有就是选3个1。组后计算答案就行了,值得注意的是,一定要多取模,能取模就取模,不要乘一起了再取模!!!。

代码:

int T,n,m,k;
int va[N];
int cnt[N];

int fact[N],infact[N];

int ksm(int a,int b)
{
	int sum = 1;
	while(b)
	{
		if(b&1) sum = sum*a%mod;
		a = a*a%mod;
		b >>= 1;
	}
	return sum;
}

void init()
{
	fact[0] = infact[0] = 1;
	for(int i=1;i<N;i++)
	{
		fact[i] = fact[i-1]*i%mod;
		infact[i] = infact[i-1]*ksm(i,mod-2)%mod;
	}
}

int C(int a,int b)
{
	if(a<b) return 0;
	return fact[a]*infact[b]%mod*infact[a-b]%mod;
}

signed main()
{
	IOS;
	init();
	cin>>n;
	for(int i=1;i<=n;i++) cin>>va[i];
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<64;j++)
		cnt[j] += (va[i]>>j)&1;
	}
	int ans = 0;
	for(int i=0;i<64;i++)
	{
		int l = cnt[i],r = n-l;
		ans = (ans+C(l,3)%mod*ksm(2,i)%mod)%mod;
		ans = (ans+C(r,2)%mod*l%mod*ksm(2,i)%mod)%mod;
	}
	cout<<ans%mod;
	return 0;
}

总结:
反正相信自己能做出来,多思考思考,想想这个题目的简化版怎么做,一步一步的去解决。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值