题面:

传送门

题目描述:

题意很简单:在一个N*M的矩阵中(N行M列),问是否可以:每行选一个整数,使他们的异或和大于0。如果不可以,输出"NIE";如果可以,输出"TAK",并输出选择的整数。
 

题目分析:

这道题刚开始想直接暴力,但看到复杂度竟然是O(500^500),就怂了。到后面仔细观察,发现题目有个数据:每个数小于1024,也就是2^10次方。会不会跟数位有关?后面分析了一下,果然是,但没时间做了,不过结束后还是A出来了。
 
异或(求大佬无视):转化为二进制后按位异或,相同位会变为0,不同位会变为1。比如3和5进行异或,3的二进制是11,5的二进制是101,结果就是110:
(注:上面最右边的第一位由于是相同位(1,1),所以变成了0,第二位是不同位,所以变成了1,第三位:因为11没有第三位,所以补一个0,变成011,然后再进行按位异或。结果就是110,然后110会转化位十进制,也就是最终结果是6,即3和5异或是6)
 
为什么要强调这个异或呢?其实重点不在于异或的规则,而在于异或转化为二进制处理的思想。我们把结果按照二进制来看:假如我们选出来的整数全部进行异或后,得到的结果转化位二进制,每个二进制位至少有一个不为0,就可以输出答案了。然后我们再看看题目数据限制:每个整数不超过1024,也就是说异或出来的结果也不超过1024,即结果的二进制位最多为9位。算下来时间复杂度是O(9*500*500),1e6左右,不会超时。所以,我们的核心思想就是:枚举结果的二进制位,尽量使结果中的二进制位含有1。剩下来就是贪心了。
 
我们再分析一下,会发现其实很容易得到这样的分类:假如当前是想让结果的第num个二进制位为1,那么,就会有:1.某一行的全部整数在第num个二进制位为1,2.某一行的全部整数在第num个二进制位为0,3.某一行的部分整数在第num个二进制位为1,另一部分在第num个二进制位为0。按照这三类,我们就可以分析这三类情况对 “异或后结果的第num个二进制位为1” 的贡献:首先,第二种情况没有任何贡献;其次,如果第一种情况是有奇数行,那么只需要使符合第三种情况的行选出来的整数在第num个二进制位为0,就可以让结果的第num个二进制位为1;如果第一种情况是有偶数行,那么只需要选出符合第三种情况的其中一行,使这一行选出的整数第num个二进制位为1,第三种情况剩下的行选出来的整数在第num个二进制位为0就行了。
 
 
AC代码(代码巨丑):
  1 #include <cstdio>
2 #include <iostream>
3 #include <cstring>
4 #include <algorithm>
5 using namespace std;
6 int n, m;
7 int G[505][505];
8 struct node{
9 int odd, even;
10 int is;
11 };
12 node row[505];
13
14 int main(){
15 scanf("%d%d", &n, &m);
16 for(int i = 0; i < n; i++){
17 for(int j = 0; j < m; j++){
18 scanf("%d", &G[i][j]);
19 }
20 }
21
22 int t;
23 for(int num = 0; num <= 8; num++){ //枚举结果的位
24 //分类
25 for(int i = 0; i < n; i++){
26 row[i].odd = 0, row[i].even = 0;
27 for(int j = 0; j < m; j++){
28 t = (G[i][j] >> num); //取出整数的第num位
29 if(t & 1) row[i].odd = 1;
30 else row[i].even = 1;
31 }
32 if(row[i].even == 1 && row[i].odd == 1){
33 row[i].is = 2; //第三种情况
34 }
35 else if(row[i].even == 1){
36 row[i].is = 0; //第一种情况
37 }
38 else row[i].is = 1; //第二种情况
39 }
40
41 int flag = 0; //标记
42 int cnt = 0; //统计第一种情况个数
43 for(int i = 0; i < n; i++){
44 if(row[i].is == 1) cnt++;
45 }
46 if(cnt % 2 == 1) flag = 1; //第一种情况为奇数个
47
48 for(int i = 0; i < n; i++){
49 if(row[i].is == 2){ //有符合第三种情况的行,也必定可以产生贡献
50 flag = 1;
51 break;
52 }
53 }
54
55 if(flag) {
56 printf("TAK\n");
57 if(cnt % 2 == 1){
58 for(int i = 0; i < n; i++){
59 if(row[i].is == 2){
60 for(int j = 0; j < m; j++){
61 t = (G[i][j] >> num);
62 if(t % 2 == 0){
63 printf("%d", j+1);
64 break;
65 }
66 }
67 }
68 else printf("%d", 1); //1是随便取的,只要在[1,m]内就行
69
70 //输出格式
71 if(i == n-1) printf("\n");
72 else printf(" ");
73 }
74 }
75 else{
76 int fd = -1;
77 //随便找符合第三种情况的一行,产生贡献
78 for(int i = 0; i < n; i++){
79 if(row[i].is == 2) {
80 fd = i;
81 break;
82 }
83 }
84
85 for(int i = 0; i < n; i++){
86 if(row[i].is == 2){
87 if(i == fd){
88 for(int j = 0; j < m; j++){
89 t = (G[i][j] >> num);
90 if(t % 2 == 1){
91 printf("%d", j+1);
92 break;
93 }
94 }
95 }
96 else{
97 for(int j = 0; j < m; j++){
98 t = (G[i][j] >> num);
99 if(t % 2 == 0){
100 printf("%d", j+1);
101 break;
102 }
103 }
104 }
105 }
106 else printf("%d", 1); //同上
107
108 //输出格式
109 if(i == n-1) printf("\n");
110 else printf(" ");
111 }
112 }
113 return 0;
114 }
115 }
116
117 printf("NIE\n");
118
119 return 0;
120 }
 
 
 
 

Codeforces Round #553 B. Dima and a Bad XOR的更多相关文章

  1. Educational Codeforces Round 71 (Rated for Div. 2)-E. XOR Guessing-交互题

    Educational Codeforces Round 71 (Rated for Div. 2)-E. XOR Guessing-交互题 [Problem Description] ​ 总共两次询 ...

  2. Codeforces Round #553 (Div. 2)

    传送门 A. Maxim and Biology 题意: 给出一个串s,问最少需要多少步操作使得串s包含"ACTG"这个子串,输出最少操作次数: 题解: 枚举每个位置 i,求出将 ...

  3. Codeforces Round #553 (Div. 2) 题解

    昨晚深夜修仙上紫记,虽然不错还是很有遗憾的. A. Maxim and Biology 看完就会做的题,然而手速跟不上 #include<cstdio> #include<iostr ...

  4. Codeforces Round #553 (Div. 2)/codeforces1151

    CodeForces1151 Maxim and Biology 解析: 题目大意 每次可以使原串中的一个字符\(+1/-1\),\(Z + 1\to A, A -1\to Z\),求至少修改多少次可 ...

  5. Codeforces Round #553 (Div. 2)B. Dima and a Bad XOR 思维构造+异或警告

    题意: 给出一个矩阵n(<=500)*m(<=500)每一行任选一个数 异或在一起 求一个 异或在一起不为0 的每行的取值列号 思路: 异或的性质  交换律 x1^x2^x3==x3^x2 ...

  6. Codeforces Round #553 (Div. 2) D题

    题目网址:http://codeforces.com/contest/1151/problem/D 题目大意:给出n组数对,(ai , bi),调整这n组数对的位置,最小化 ∑(ai*( i -1)+ ...

  7. Codeforces Round #553 (Div. 2) C题

    题目网址:http://codeforces.com/contest/1151/problem/C 题目大意:给定奇数集和偶数集,现构造一个数组,先取奇数集中一个元素1,再取偶数集二个元素2,4,再取 ...

  8. Codeforces Round #553 (Div. 2) B题

    题目网址:http://codeforces.com/contest/1151/problem/B 题目大意:给定一个n*m的矩阵,问是否可以从每一行中选择一个数,使得这n个数异或大于0,如果可以还要 ...

  9. Codeforces Round #553 (Div. 2) A题

    题目网址:http://codeforces.com/contest/1151/problem/A 题目大意:给定一个由大写字母构成的字符串和它的长度,有这样的操作,使任意一个字母变成与其相邻的字母, ...

随机推荐

  1. sdut2878 环形依赖的DP(高斯消元,剪枝后的模板

    这题的状态是循环依赖的有环.. 之前一道概率DP,类似有环..但是它是可以消掉的 比如dp[i]=0.3*dp[i+1]+0.2*dp[i+2]+0.5*dp[i]; 完全可以变成,0.5*dp[i] ...

  2. 力扣566. 重塑矩阵-C语言实现-简单题

    题目 传送门 在MATLAB中,有一个非常有用的函数 reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据. 给出一个由二维数组表示的矩阵,以及两个正整数r和c,分别表示想要 ...

  3. CSS Multiple Columns

    CSS Multiple Columns CSS layout column-count column-gap column-rule-style column-rule-width column-r ...

  4. HTTP vs HTTP/2 vs HTTP/3 (QUIC)

    HTTP vs HTTP/2 vs HTTP/3 (QUIC) Nginx HTTP/1.1 HTTP/2 HTTP/3 (QUIC) HTTPS 计算机网络协议 OSI 协议簇 (7) TCP/IP ...

  5. vscode & peacock extension

    vscode & peacock extension https://marketplace.visualstudio.com/items?itemName=johnpapa.vscode-p ...

  6. perl 在windows上获取当前桌面壁纸

    更多 #!/usr/bin/perl # 在windows获取当前的桌面壁纸 # See also: https://www.winhelponline.com/blog/find-current-w ...

  7. go-admin在线开发平台学习-1[安装、配置、启动]

    项目介绍 go-admin 是一个中后台管理系统,基于(gin, gorm, Casbin, Vue, Element UI)实现.主要目的是为了让开发者更专注业务,减少重复代码的编写,节省时间,提升 ...

  8. 多种转弯角度的PBN旁切转弯图例分析

    无论世界怎样变化,我们依然是有点阳光就灿烂.面对世界的未知,最好的状态是勇敢的去面对,努力的去生活. 今天我们继续来聊一下PBN旁切转弯. PBN转弯保护区的结构通常都与它们的转弯角度大小有关,转弯角 ...

  9. Flutter 中不得不会的 mixin

    mixin 是 Dart 中非常重要的概念,对于未接触过此概念的Coder来说尤其重要,最近看源码的时候,由于对 mixin 不熟悉导致理解出现偏差,走了很多弯路,所以这篇文章介绍一下 mixin 概 ...

  10. nginx日志文件切分

    定义cut_nginx_log.sh 日志文件脚本如下 #!/bin/bash#LOGS_PATH为日志存放路径LOGS_PATH=/weblog/nginx/logsYESTERDAY=$(date ...