题目描述
已知 aaa,你可以选 mmm 个数,满足每个数均为 333 的倍数,且 mmm 个数的或为 aaa.
试最小化 mmm.
数据范围
对 100%100\%100% 的数据,T≤105T\le 10^5T≤105,a≤1018a\le 10^{18}a≤1018.
题解
挺水的一题
如果 aaa 是 333 的倍数,则直接用 aaa 即可
否则考虑能否用两个 333 的倍数的数或起来为 aaa
把 aaa 拆位,显然 2i%3=1/22^i\%3=1/22i%3=1/2 ,所以把 %3\%3%3为 111 的和 %3\%3%3 为 222 的位置分开,然后多的那一边拿出两个数相加,这样就可以放在另一边了,重复上述操作直到两边的差不超过 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;
}