zoukankan      html  css  js  c++  java
  • Codeforces 1107D

    在这里插入图片描述在这里插入图片描述

    题目大意:

    给出一个n x n 的矩阵A,只有01两种元素组成,确保给的一定是4的倍数,接下来要对该矩阵进行压缩,压缩后的矩阵为B,边长为x,要求A i j 等于比B i / x j / x (i / x 向上取整)。如n = 8,压缩后的x为2,所以原来a 1 1 就等于 B 1 1 B1 2 B 2 1 B 2 2。询问压缩后的矩阵最大边长是多少,先输入一个n,然后每行输入一个n / 4位的十六进制数,需要先将十六进制数转为二进制的01存入矩阵。

    解题思路:

    要使得1个元素的值等于x * x 个元素的值,就要使这些值都相等,而该矩阵的值只有0和1,就可以把问题转化为:将一个大矩阵转化为n等分的全0或全1的矩阵,矩阵最大边长是多少。,也就是说,我们需要把n x n 的矩阵转化为(n / x)2个矩阵,每个边长是x,这些矩阵元素要么是全0要么是全1,
    这样就好办了,维护这个矩阵的二维前缀和,从大到小枚举可能的答案x,然后分块求前缀和,当一块的前缀和 = 0或 = x * x,说明全0或全1,即可num++,最后统计num是不是等于(n / x)2,如果等于说明所有部分都符合要求,退出循环,输出答案即可。

    Code:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    #include <map>
    #include <set>
    #include <cstring>
    using namespace std;
    const int N = 5500;
    int mp[N][N], sum[N][N];
    int main()
    {
    	ios::sync_with_stdio(false);
    	int n;
    	cin >> n;
    	for (int i = 1; i <= n; i ++)//将十六进制转为二进制存入矩阵
    	{
    		string s;
    		cin >> s;
    		for (int j =0, idx = 0; j < n / 4; j ++, idx ++)
    		{
    			int t = isdigit(s[idx]) ? s[idx] - '0' : s[idx] - 'A' + 10;
    			mp[i][j * 4 + 1] = (t & 8) >> 3;
    			mp[i][j * 4 + 2] = (t & 4) >> 2;
    			mp[i][j * 4 + 3] = (t & 2) >> 1;
    			mp[i][j * 4 + 4] = t & 1;
    		}
    	}
    	memset(sum, 0, sizeof sum);
    	for (int i = 1;  i<= n; i ++)//二维前缀和
    	  for (int j = 1; j <= n; j ++)
    	    sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + mp[i][j];
    	int ans = 1;
    	bool flag = false;
    	for (int i = n; i >= 1; i--)
    	{
    		if(n % i)  continue;//枚举的部分必须整除才保证可以均分
    		int num1 = 0, num2 = 0;
    		for (int j = i; j <= n; j += i)
    		    for (int k = i; k <= n; k += i)
    		    {
    			    if (sum[j][k]-sum[j - i][k] - sum[j][k - i] + sum[j - i][k - i] == 0)  num1++;//判断全0或全1
    			    else if (sum[j][k]-sum[j - i][k] - sum[j][k - i]+sum[j - i][k - i] == i * i)  num2++;
    
    		    }
    		int x = n / i;//一共有x平方个部分
    		if (num1 + num2 == x * x)
    		{
    			flag = true;
    			ans = i;
    		}
    		if (flag)
    		  break;
    	}
    	cout << ans << endl;
    	return 0;
    }
    
  • 相关阅读:
    弹窗拖拽组件开发应用
    高级事件的运用
    常见排序算法(JS版)
    原生js实现仿window10系统日历效果
    原生js实现吸顶导航和回到顶部特效
    OVN实战---《The OVN Gateway Router》翻译
    OVN实战---《An Introduction to OVN Routing》翻译
    OVN实战---《A Primer on OVN》翻译
    深入理解CNI
    《CNI specification》翻译
  • 原文地址:https://www.cnblogs.com/Hayasaka/p/14294177.html
Copyright © 2011-2022 走看看