티스토리 뷰

[Codeforces 1151B] Dima and a Bad XOR - 1600


문제 설명 : 

n by m 크기의 행렬이 주어진다. 행렬의 각 열에서 임의의 숫자를 하나씩 뽑아서 xor를 취한다. 그 결과가 0이 나오지 않는 경우가 있다면 각 열에서 몇 번째 수를 xor해야하는지 출력하고, 아니면 반드시 결과가 0이 나올 수 밖에 없는지 구하는 문제이다.


풀이 : 

xor연산의 간단한 특성을 알아야 한다. 

a ^ b =0 을 만족한다면 a = b도 반드시 만족한다. 

또한 a^b = 0 이고  b≠c라면, a^c ≠ 0 도 반드시 성립한다.

이 두 가지 성질을 가지고 문제를 풀자.


이 문제에서의 관건은 어떤 수들을 xor해야 0이 나오지 않게 만드냐이다. 처음에는 일단 각 열의 첫 번째 원소들(mat[i][1])을 xor를 취해보자. 만약 그 결과가 운좋게 0이 아닌 값이 나오면 그냥 그게 답이 된다. 그런데 당연히 0이 나올 수도 있다. 그렇다면 과연 어떤 수 들로 바꿔주어야 할까? 정답은 '아무 숫자로만 바꾸면 된다'이다. 위의 특성에서 언급했다시피 a^b = 0 이라면, b≠c를 만족하는 a^c ≠ 0 도 성립한다.. 그런데 또 여기서 각 열에서 등장하는 숫자가 단 하나밖에 없다면, 즉 다른 값을 취할 수 있는 선택지가 없다면 결과가 0이 나올 수 밖에 없다. 그래서 행렬의 각 열에서 첫 번째 원소와 다른 수가 단 하나라도 존재한다면 0이 아닌 값을 반드시 만들 수 있고, 모든 열에서 단 하나의 수 밖에 등장하지 않는다면 불가능하다.


주의할 점 : 

-


배운 점 : 

xor의 신기한 특징을 배웠다.


코드 : 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<functional>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<assert.h>
#include<stdlib.h>
#include<stack>
using namespace std;
/*********************Contest Template***********************/
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<long long,long long> pll;
#define FASTIO ios_base::sync_with_stdio(false);cin.tie(0);
struct S{
    int a,b; S(){}S(int _a,int _b)
    { a=_a; b=_b; }
    const bool operator<(const S &o) const{
        return a<o.a;}
};
priority_queue<int,vector<int>,greater<int>> mpq;
const int SPACE=0,NL=1;  string exm;
inline void showAll(vector<int> &v,int sep){ //0=space,1="\n"
    for(int &here:v) printf("%d%c",here,(sep)?'\n':' '); }
inline void exf(void){ cout<<exm<<"\n"; exit(0); }
/*********************Contest Template***********************/
const int SIZE= 509;
int mat[SIZE][SIZE];
int ans[SIZE];
 
int main(){
    int n,m;    scanf("%d %d",&n,&m);
 
    exm="NIE";
    for(int i=1 ; i<=n ; i++){
        for(int j=1 ; j<=m ; j++){
            scanf("%d",&mat[i][j]);
        }
    }
    for(int i=1 ; i<=n ; i++) ans[i]=1;
 
    int sum=0;
    pii diff={0,0};
    for(int i=1 ; i<=n ; i++){
        int first=mat[i][1];
        for(int j=2 ; j<=m ; j++){
            if(first!=mat[i][j]) diff={i,j};
        }
        sum ^= first;
    }
    if(sum==0){
        if(diff.first==0) exf();
        ans[diff.first]=diff.second;
    }
    printf("TAK\n");
    for(int i=1 ; i<=n ; i++)
        printf("%d ",ans[i]);
    return 0;
}
cs


'Problem Solving > Number Theory' 카테고리의 다른 글

[Codeforces 1011E] Border  (0) 2019.05.11
[Codeforces 1025B] Weakened Common Divisor  (0) 2019.05.07
댓글