洛谷 P5461 赦兔战俘

题目背景

借助反作弊系统,一些在月赛有抄袭作弊行为的选手被抓出来了!

题目描述

现有 2^n*2^n (n10) 名作弊者站成一个正方形方阵等候 kkksc03 的发落。kkksc03 决定赦免一些作弊者。他将正方形矩阵均分为 4 个更小的正方形矩阵,每个更小的矩阵的边长是原矩阵的一半。其中左上角那一个矩阵的所有作弊者都将得到赦免,剩下 3 个小矩阵中,每一个矩阵继续分为 4 个更小的矩阵,然后通过同样的方式赦免作弊者……直到矩阵无法再分下去为止。所有没有被赦免的作弊者都将被处以棕名处罚。

给出 nn,请输出每名作弊者的命运,其中 0 代表被赦免,1 代表不被赦免。

输入格式

一个整数 n

输出格式

2^n *2^n的 01 矩阵,代表每个人是否被赦免。数字之间有一个空格。

输入输出样例

输入 #1
3
输出 #1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 1 1
0 0 0 0 0 1 0 1
0 0 0 0 1 1 1 1
0 0 0 1 0 0 0 1
0 0 1 1 0 0 1 1
0 1 0 1 0 1 0 1
1 1 1 1 1 1 1 1

自己的想法是用递归来写,代码是这样的:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
int n,p=1,a[1050][1050];
void di(int l,int x,int y )
{
    if(l == 2)
    {
        a[x][y] = 0;
        return ;
    }
    for(int i = x ; i <= x + l/2 - 1 ; i++)
    {
        for(int j = y ; j <= y + l/2 -1 ; j ++)
        {
            a[i][j] = 0;
        }
    }
    
    di(l/2, x+l/2, y);
    di(l/2, l/2+x, l/2+y);
    di(l/2, x, y+l/2);
}
int main()
{
    cin >> n;
    for(int i = 1 ; i <= n ; i ++)
    {
        p*=2;
    }
    
    for(int i = 1 ; i <= p ;i ++)
    {
        for(int j = 1 ; j <= p ; j++)
        {
            a[i][j] = 1;
        }
    }
    
    di(p,1,1);
    
    for(int i = 1 ; i <= p ; i ++) {
        for(int j = 1 ; j <= p ; j++)
        {
            cout << a[i][j];
        j == p ? cout << endl:cout << " "; 
        }
        cout << endl;
    }
}

因为是2的n次方的二维数组,输入n,要求出2^n 的值,并把a[2^n][2^n]全设为1,等递归的时候,对应情况设置为0;

因为每次进行的步骤都是一样的,都是讲正方形的二维数组的长宽除2,然后将左上角的所有1变为0,因此想到了递归,直到边长为2了,只用把此正方形的最左上角设置为0,即可结束递归。

但是看了看大佬的方法,还有更简便的,只用了位运算的方法!

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>

int n;
int a[1234][1234];
int main()
{
    scanf("%d",&n);
    n = (1<<n);  //左移
    a[0][n+1] = 1;
    for(re int i=1;i<=n;++i)
    {
        for(re int j=1;j<=n;++j)
        {
            a[i][j] = a[i-1][j] ^ a[i-1][j+1];  //异或
            printf("%d ",a[i][j]);
        }
        printf("\n");
    }
    return 0;
}

仔细观察输出的数据,其实都是它上方的数字异或它上方右边的数字,其实就是不进位加法。

于是乎,开始复习一下,二进制的位运算吧!!!

位运算:

其实二进制的位运算不难掌握,共有5种:与,或,异或,左移,右移。

 归纳一下:(二进制下用1表示真,0表示假)

与其实就是数学的且,两个都为真才是真。

或则和数学的一样,有真为真。

异或是,两者相同为0,不同为1

猜你喜欢

转载自www.cnblogs.com/wtzmz/p/12982398.html