刷题 位运算 位掩码

2023.12.7 1903D1

 

解题思路

题目一眼long long,所以从大到小迭代每一个位(262到20

因为要与&起来最大,尽量把高位的0在不超过步数的情况下整成1,所以如果第i位是0,就把ai增加到下一位变成1

只有能走到最后的i是答案的二进制第i位为1,直接加在ans上

 

代码

 

#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
ll a[100005],b[100005];
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	int n,q;
	cin>>n>>q;
	for(int i=1;i<=n;i++)cin>>a[i];
	while(q--)
	{
		ll k,ans=0;
		cin>>k;
		for(int i=1;i<=n;i++)b[i]=a[i];
		for(int i=62;i>=0;i--)
		{
			ll sum=0;
			for(int j=1;j<=n;j++)
			{
				if(b[j]&1ll<<i)continue;
				ll p=(b[j]/(1ll<<i)*(1ll<<i)+(1ll<<i));
				p+=ans^(p&ans);//保证p变的时候别把ans本来有的变走了
				sum+=p-b[j];
				if(sum>k)break;
			}
			if(sum>k)continue;
			for(int j=1;j<=n;j++)
			{
				if(b[j]&1ll<<i)continue;
				ll p=(b[j]/(1ll<<i)*(1ll<<i)+(1ll<<i));
				p+=ans^(p&ans);
				b[j]=p;//相应的改变数组
			}
			ans+=1ll<<i;
			k-=sum;
		}
		cout<<ans<<endl;
	}
	return 0;
}
posted @ 2023-12-07 23:49  modemingzi  阅读(11)  评论(0)    收藏  举报