蓝桥杯算法训练超全习题题解——ALGO-194.审美课**

每日刷题(六十一)

ALGO-194、审美课

在这里插入图片描述
在这里插入图片描述
这个题绝对不可以用暴力破解法,这样会远远超出题目要求的时间。

我们可以换个角度看问题。要求答案完全相反的对数,而且给出的是1和0,我们很容易想到位运算这一类知识点。

由于最多20列,就相当于最大数是220-1,那么我们设一个数组ans来存数的种类的数目。这里有点难懂,没事,继续看就会懂了。我们首先要存数,但我们要处理一下,把传统思路的二维数组转化为一维数组,也就是一个同学的答案对应一个数,我们通过左移运算符每次传入一列的值就左移一次。最后再将得到的一个孩子的答案数字作为ans的下标,然后这个下标对应的值+1。

当值处理完后,我们用1 << m - 1得到答案最大的数字st(全1),然后进行n次循环,把每个a[i]与st异或一下,得到的数作为下标,sum += ans[cnt]
因为ans这个数组实际的意义就是存答案的重复次数,每个孩子的答案对应不同的下标,如果有很多孩子的答案都是这个数tmp,那么ans这个数值的下标的值就会很大。

注意,最终得到的sum要除以2,因为我们是遍历了n个孩子,如果存在完全相反的情况,那么我们的sum会重复加两次。

详细C代码如下:

#include<stdio.h>
#include<string.h> 
int ans[1048576] = {0};
int a[50001];

int main()
{
	int n, m;
	scanf("%d %d", &n, &m);
	memset(a, 0, sizeof(a));
	int i, j;
	for(i = 0; i < n; i++)
	{
		for(j = 0; j < m; j++)
		{
			int tmp;
			scanf("%d", &tmp);
			a[i] = (a[i] << 1) + tmp;
		}
     	ans[a[i]]++;
	}
	
	int st = 0;
	st = (1 << m) - 1;		//全1 
	int sum = 0;
	for(i = 0; i < n; i++)
	{
		int cnt;
		cnt = a[i] ^ st;		//异或得到完全相反的同学答案 
		sum += ans[cnt];
	}
	printf("%d\n", sum / 2);
	return 0;
}

样例运行结果如下:
在这里插入图片描述

如果喜欢我的文章,请记得三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持,下期更精彩!!!

发布了99 篇原创文章 · 获赞 16 · 访问量 5905

猜你喜欢

转载自blog.csdn.net/qq_44631615/article/details/105358363