题意
给你一个n,问至少有几个数或运算起来可以等于n,并且输出数量和这个几个数(且这几个数是 3 的倍数)。题目说明给的n一定符合条件(不会输出n=1 之类不存在情况)。
题解
题目说 n 一定符合条件,所以不考虑n==1 或 n == 4之类的数,此类数不符合条件
分类讨论
当 n % 3 == 0 时,直接输出 n ,不用和其他数异或
否则将n转换为二进制,因为二进制数 %3 的规律为 1 2 1 2 1 2 1 2
当 n % 3 == 1时,
①当 二进制数位有 至少2 个 mod 3= 1,设为 p,q, 则两个数为 (n-p, n-q)
②当n中的二进制位恰好有一个 mod 3= 1,那么设mod 3 = 1 的这个位为p,mod 3 = 2的某个位为q,取(a-p, p+1)
③当n中的二进制没有 mod 3 = 1的,那么假设有三个mod = 2 的位p, q, r我们去(a-p-q, p+q+r);
当n % 3 == 2 时,和n%3 == 1的情况相反
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
int t;
cin >> t;
ll b[100];
b[0] = 1;
for(int i = 1; i <= 60; i++){ // 预处理2的指数,2的60次 > 10的18次
b[i] = b[i-1] * 2;
}
while(t--){
ll s, w, ans1, ans2;
cin >> s;
w = s;
if(s % 3 == 0){ // 当余3 == 0 时
cout << 1 << " " << s << endl;
continue;
}
ll a[100];
int j = 60, a1 = 0, a2 = 0, c1[60], c2[60];
memset(a, 0, sizeof(a));
memset(c1, 0, sizeof(c1));memset(c2, 0, sizeof(c2));
for(int i = 60; i >= 0; i--){ // 将数 转换为 二进制
if(s - b[i] >= 0){
a[j] = 1;
if(j % 2 == 0){ // 二进制数 % 3 == 1的情况
c1[a1] = j;
a1++;
}
else{ // 二进制 % 3 == 2的情况
c2[a2] = j;
a2++;
}
s = s - b[i];
}
else{
a[j] = 0;
}
j--;
}
/*for(int i = 0; i <= 10; i++){
cout << a[i];
}
cout << endl<< a1 << " " << a2 << endl;*/
if(w % 3 == 1){ // 输入的数 % 3 == 1
if(a1 >= 2){ // 有至少两个二进制数位 % 3 == 1 (1 或4 或16 .... )
ans1 = w - b[c1[0]];
ans2 = w - b[c1[1]];
}
else if(a1 == 1){ // 正好一个
ans1 = w - b[c1[0]];
ans2 = b[c1[0]] + b[c2[0]];
}
else{ // 一个没有
ans1 = w - b[c2[0]] - b[c2[1]];
ans2 = b[c2[0]] + b[c2[1]] + b[c2[2]];
}
}
else{ // %3 == 2
if(a2 >= 2){
ans1 = w - b[c2[0]];
ans2 = w - b[c2[1]];
}
else if(a2 == 1){
ans1 = w - b[c2[0]];
ans2 = b[c2[0]] + b[c1[0]];
}
else{
ans1 = w - b[c1[0]] - b[c1[1]];
ans2 = b[c1[0]] + b[c1[1]] + b[c1[2]];
}
}
cout << 2 << " " << ans1 << " " << ans2 << endl;
}
return 0;
}