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