题意
给你一个 a a a让你求一个最小的集合 S S S, S S S中所有的数都是 3 3 3的倍数,且 S S S中所有的数按位或的和为 a a a,输出 S S S中的元素的个数以及元素
思路
显然
a
%
3
=
=
0
a\%3==0
a%3==0时,集合
S
S
S就只含一个
a
a
a。根据按位或的性质,将
a
a
a转化为二进制之后,
S
S
S中的元素只会是
a
a
a的二进制中权值为一的组合。由于二进制的位权模
3
3
3只可能为
1
1
1或为
2
2
2,即
2
0
=
1
(
m
o
d
3
)
2^0=1(\ mod\ 3)
20=1( mod 3)
2
1
=
2
(
m
o
d
3
)
2^1=2(\ mod\ 3)
21=2( mod 3)
2
2
=
1
(
m
o
d
3
)
2^2=1(\ mod\ 3)
22=1( mod 3)
⋮
\vdots
⋮
2
n
=
n
%
2
+
1
(
m
o
d
3
)
2^n=n\%2+1(\ mod\ 3)
2n=n%2+1( mod 3)
已知
a
a
a化为二进制,可以表示为
a
=
2
p
1
+
2
p
2
+
2
p
3
+
⋯
+
2
p
k
a=2^{p_1}+2^{p_2}+2^{p_3}+\cdots+2^{p_k}
a=2p1+2p2+2p3+⋯+2pk
然后考虑
a
%
3
=
=
1
a\%3==1
a%3==1的情况,由于有
a
=
2
p
1
+
2
p
2
+
2
p
3
+
⋯
+
2
p
k
a=2^{p_1}+2^{p_2}+2^{p_3}+\cdots+2^{p_k}
a=2p1+2p2+2p3+⋯+2pk,故
2
p
1
+
2
p
2
+
2
p
3
+
⋯
+
2
p
k
≡
1
(
m
o
d
3
)
2^{p_1}+2^{p_2}+2^{p_3}+\cdots+2^{p_k}\equiv 1(\ mod\ 3)
2p1+2p2+2p3+⋯+2pk≡1( mod 3)
由于
2
n
2^n
2n只会是
1
1
1或者
2
2
2,那么根据同余式的两边可以可以加减相同的数,那么考虑,若
a
a
a的二进制中找一个
2
x
%
3
=
1
2^x \% 3=1
2x%3=1或
2
x
1
%
3
=
2
2^{x_{1}} \% 3=2
2x1%3=2和
2
x
2
%
3
=
2
2^{x_{2}} \% 3=2
2x2%3=2(
2
x
1
+
2
x
2
%
3
=
1
2^{x_{1}}+2^{x_{2}}\%3=1
2x1+2x2%3=1)那么令
x
=
2
x
x=2^x
x=2x,那么
a
−
x
a-x
a−x肯定为3的倍数,那我们再找一个
2
y
%
3
=
2
2^y\%3=2
2y%3=2或者找两个
2
y
%
3
=
1
2^{y}\%3=1
2y%3=1的,令
y
=
2
y
y=2^y
y=2y,那么
x
+
y
≡
0
(
m
o
d
3
)
x+y\equiv 0(\ mod \ 3)
x+y≡0( mod 3),那么答案就是
a
−
x
a-x
a−x和
x
+
y
x+y
x+y了,实际上
S
S
S最小为2就可以满足了,由于题目输入的
a
a
a有解所有肯定能找到这样的
x
x
x和
y
y
y
a
%
3
=
=
2
a\%3==2
a%3==2同理
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pb push_back
vector<int>ans;
void solve(int n){
int res;
vector<int>yu1,yu2;
if(n%3==0){
ans.pb(1);
ans.pb(n);
return;
}
for(int j=0;j<62;++j){
if(n>>j&1){
if((1LL<<j)%3==1){
yu1.pb(1LL<<j);
}
else{
yu2.pb(1LL<<j);
}
}
}
ans.pb(2);
if(n%3==1){
if(yu1.size()){
int res=yu1.back();
yu1.pop_back();
ans.pb(n-res);
//找剩下的能加出来余2的
if(yu1.size()>=2){
res+=yu1.back();
yu1.pop_back();
res+=yu1.back();
yu1.pop_back();
}
else{//
res+=yu2.back();
}
ans.pb(res);
//end
return;
}
else{
res=yu2.back();
yu2.pop_back();
res+=yu2.back();
yu2.pop_back();
ans.pb(n-res);
res+=yu2.back();
ans.pb(res);
}
return;
}
if(n%3==2){
if(yu2.size()){
res=yu2.back();
yu2.pop_back();
}
else if(yu1.size()>=2){
res=yu1.back();
yu1.pop_back();
res+=yu1.back();
yu1.pop_back();
}
ans.pb(n-res);
//找剩下加出来能余1的
if(yu1.size()){
res+=yu1.back();
}
else{
res+=yu2.back();
yu2.pop_back();
res+=yu2.back();
}
ans.pb(res);
return;
}
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0);
int T;
while(cin>>T){
while(T--){
ans.clear();
int n;cin>>n;
solve(n);
for(auto tar:ans) cout<<tar<<' ';
cout<<endl;
}
}
return 0;
}