牛客暑假多校训练营第一场-1001 Mod, Or and Everything

71 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

传送门

题意:

给你一个n,求n分别模上1到n之后相或的值

思路:

由或的性质可以得知:只需要找到所有模数在二进制位上出现的1的并集即可(并且对于同一模数,多个该模数和单个该模数对答案的贡献一样),而对于此题来说,我们肯定可以在模数中找到一个从1开始且公差为1的等差数列,因而我们只需要找到模数的最大值,就可以得出答案。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll a[100];

int main()
{
	int t;
	cin>>t;
	for(int i = 1; i <= 60; i++)
	{
		a[i] = pow(2,i-1);
	}
	while(t--)
	{
		ll n;
		cin>>n;
		int cnt = 0;
		ll now = 1;
		for(int i = 1; i <= 64; i++)
		{
			now *= 2;
			if(now >= n)
			{
				cnt = i-1;
				break;
			}
		}
		ll ans = 0;
		for(int i = 1; i <= cnt; i++)
		{
			ans += a[i];
		}
		cout<<ans<<endl;
	}
}