#4508. Triples I

探讨如何选择最少数量的3的倍数,使它们的按位或等于给定值。通过分析数的二进制表示,将问题简化为平衡两边数的数量,以达到最小化选择数目的目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

已知 aaa,你可以选 mmm 个数,满足每个数均为 333 的倍数,且 mmm 个数的或为 aaa.

试最小化 mmm.

数据范围

100%100\%100% 的数据,T≤105T\le 10^5T105a≤1018a\le 10^{18}a1018.

题解

挺水的一题

如果 aaa333 的倍数,则直接用 aaa 即可

否则考虑能否用两个 333 的倍数的数或起来为 aaa

aaa 拆位,显然 2i%3=1/22^i\%3=1/22i%3=1/2 ,所以把 %3\%3%3111 的和 %3\%3%3222 的位置分开,然后多的那一边拿出两个数相加,这样就可以放在另一边了,重复上述操作直到两边的差不超过 111 即可

代码

#include <bits/stdc++.h>
#define _(d) while(d(isdigit(c=getchar())))
typedef long long LL;using std::swap;
LL R(){char c;_(!);LL x=c^48;_()x=(x<<3)+(x<<1)+(c^48);return x;}
int T,t[2],m,u,v;LL a,p[2][65],x,y,j;
int main(){
	for (scanf("%d",&T);T--;){
		a=R();
		if (a%3==0){printf("1 %lld\n",a);continue;}
		j=1;t[0]=t[1]=0;
		for (int i=0;j<=a;i++,j<<=1)
			if (a&j) p[i&1][++t[i&1]]=j;
		u=0;v=1;if (t[0]>t[1]) swap(u,v);
		while(t[v]-t[u]>1)
			p[u][++t[u]]=p[v][t[v]]|p[v][t[v]-1],t[v]-=2;
		u=0;v=1;if (t[0]>t[1]) swap(u,v);
		x=0,y=0;for (int i=1;i<=t[u];i++)
			x|=(p[u][i]|p[v][i]),y|=(p[u][i]|p[v][i+1]);
		printf("2 %lld %lld\n",x,y);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值