HDU 6313 - Hack It [2018杭电多校联赛第二场 E](数论构造)

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=6313

【题意】
构造一个n*n的矩阵,矩阵元素只有0和1,要求该矩阵的任意一个子矩阵的四个角不能同时为1,同时该矩阵中所有1的个数要大于85000个,没有输入,输出符合要求的n的值和这个矩阵即可.

【思路】
看了大佬讲的构造方法,反正我自己是想不出来。构造方法是这样的,找一个素数p,然后构造出来的矩阵的行数和列数是p*p,拿p=5举例,构造的结果如下。

10000 01000 00100 00010 00001
10000 00100 00001 01000 00010
10000 00010 01000 00001 00100
10000 00001 00010 00100 01000
10000 10000 10000 10000 10000

01000 00100 00010 00001 10000
01000 00010 10000 00100 00001
01000 00001 00100 10000 00010
01000 10000 00001 00010 00100
01000 01000 01000 01000 01000
…..
       只写了前10行,还有15行没写,但已经能看出规律了
       首先每行5个1,总共5^3=125个1,根据这个来估算一下最后的p应该是47,使得所有1的个数大于85000
       然后再看,前5行第0组1的位置都是第0个,第0行中后一组1的位置是前一组的位置在mod 5的意义下+0,第1行中后一组1的位置是前一组的位置在mod 5的意义下+1,同理第2行+2,第三行+3,第四行+4…
       然后5~9行的每一组都是0~4行中的每一组循环右移一位得到的,同理10~14行是循环右移两位…规律基本上就是这样,写法很多,我看到一个比较简洁的贴过来学习一下

#include<bits/stdc++.h>
using namespace std;

const int p=47;
const int maxn=p*p+50;

int ans[maxn][maxn];

int main(){
    for(int r=0;r<p*p;++r){
        int a=r/p;
        int b=r%p;
        for(int i=0;i<p;++i){
            int c=i*p+(i*a+b)%p;
            ans[r][c]=1;
        }
    }
    puts("2000");
    for(int i=0;i<2000;++i){
        for(int j=0;j<2000;++j){
            printf("%d",ans[i][j]);
        }
        puts("");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xiao_k666/article/details/81236704