2019 가축 오프 더 학교 네 번째 질문 D
문제의 의미
당신에게 부여 \ (N- 형의 \)를 , 또는이 같아야 수있는 작업의 최소한 몇 수를 요청 \합니다 (N- \) , 출력과 몇 가지 숫자의 번호입니다. 제목 설명에 \ (\ N-) 의 조건을 만족한다 (출력하지 \ (N = 1 \) 등이 존재하지 않음).
생각
우리는 게임 테이블이 적어도 n 개의 형성 될 수있다 알 수 \ (1 \) 하나 또는 \ (2 \) 또는 이들의 수.
- 첫째, 미리 판단 \ (N 개의 \ % 3 == 0 \) 이 출력 (\ n \) 자체 그것에
숫자는 다른 제조 될 수있다 \ (2 \) OR 작업 번호.
- \ (\ N-) 이진으로, 각각의 비트 1은 수집로 추출한다 (R & 중위 \) \
- 找到两个集合\ (A, B \) , \ (a \ 컵 B = R \)
\ (NUM1 = \ sum_ I = {0} ^ {a.size ()} X_ {I} (X_ {I} \에서) \)
\ (NUM1 \ % 3 == 0 \)
\ (NUM2 = \ sum_ I = {0} ^ {b.size ()} Y_ {I} (Y_ {I} \ B)에서 \ )
\ (NUM2의 \ % 3 == 0 \) - 그리고 넣어했다 \ (A, B \) 약간의 컬렉션까지 추가 답변 할 수 있습니다.
샘플 (WA는 두 가지 예 울 해결)
2
85
682
(1010101、1010101010)上面两个样例的二进制
AC 코드
#include<bits/stdc++.h>
#define mes(a, b) memset(a, b, sizeof a)
using namespace std;
typedef long long ll;
int a[100];
int ans[3];
void solve(ll x){ //转换n为二进制
int i = 0;
while(x){
a[i++] = x%2;
x /= 2;
}
}
int main(){
int t;
ll n;
scanf("%lld", &t);
while(t--){
scanf("%lld", &n);
if(n % 3ll == 0){
printf("1 %lld\n", n);
continue;
}
mes(a, 0);
solve(n);
ans[1] = ans[2] = 0; //分别计算二进制位为1的数字取模3分别为1和2的数量
for(int i = 0; i <= 64; i++){
if(a[i] == 1){
int num = (1ll<<i)%3ll;
ans[num]++;
}
}
int sum = ans[1] + ans[2]*2;
int b[3][3];
mes(b, 0);
if(sum % 3 ==1){ //强行分组(本人比较菜只会这样写)
if(ans[1] == 0){
b[1][1] = 0;
b[1][2] = ans[2] - 2;
b[2][1] = 0;
b[2][2] = 3;
}
else{
b[1][1] = ans[1]-1;
b[1][2] = ans[2];
if(ans[2] == 0){
b[2][1] = 3;
}
else{
b[2][1] = 1;
b[2][2] = 1;
}
}
}
else if(sum %3 == 2){
if(ans[2] == 0){
b[1][1] = ans[1]-2;
b[1][2] = 0;
b[2][1] = 3;
b[2][2] = 0;
}
else{
b[1][1] = ans[1];
b[1][2] = ans[2]-1;
if(ans[1] == 0){
b[2][1] = 0;
b[2][2] = 3;
}
else{
b[2][1] = 1;
b[2][2] = 1;
}
}
}
ll num1 = 0, num2 = 0;
for(int i = 0; i < 64; i++){
if(a[i] == 1){
int num = (1ll<<i)%3;
if(b[2][num] == ans[num]){
num2 += (1ll<<i);
b[2][num]--;
}
if(b[1][num] > 0){
num1 += (1ll<<i);
b[1][num]--;
}
ans[num]--;
}
}
printf("2 %lld %lld\n", num1, num2);
}
return 0;
}