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