zoukankan      html  css  js  c++  java
  • 洛谷 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("
    ");
        }
        return 0;
    }

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

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

    位运算:

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

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

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

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

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

  • 相关阅读:
    Java程序:从命令行接收多个数字,求和并输出结果
    大道至简读后感
    大道至简第一章读后感Java伪代码
    Creating a SharePoint BCS .NET Connectivity Assembly to Crawl RSS Data in Visual Studio 2010
    声明式验证超时问题
    Error message when you try to modify or to delete an alternate access mapping in Windows SharePoint Services 3.0: "An update conflict has occurred, and you must re-try this action"
    Upgrading or Redeploying SharePoint 2010 Workflows
    Upgrade custom workflow in SharePoint
    SharePoint 2013中Office Web Apps的一次排错
    How to upgrade workflow assembly in MOSS 2007
  • 原文地址:https://www.cnblogs.com/wtzmz/p/12982398.html
Copyright © 2011-2022 走看看