Nowcoder Kimi to Kanojo to Kanojo no Koi wannafly camp 重现赛 构造法

本文介绍了一种算法,用于解决特定的数学问题,即构造一个nxn的方阵,确保每行每列都是从1到n的排列,且满足特定条件。文章详细阐述了针对奇数、2的指数和偶数的不同构造策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


                                                               nowcoder Kimi to Kanojo to Kanojo no Koi

如果你希望解锁Miyuki的手机,你需要回答30个问题,只有你非常关注Miyuki才能全部解答正确。而且,根据“你”的不同,Miyuki的行为也是不一样的,对于不同的"你",答案相同的概率为。可以说,对于每个不同的"你",都有一个唯一的Miyuki。
不过因为Miyuki现在心情很好,所以你只需要回答一个问题。给一个正整数 n,要求构造一个 n x n 的方阵 A,使得方阵的每一行,每一列都分别是一个 的排列,并且对于所有的 1 ≤ i < j ≤ n, 有 Ai,j ≠ Aj,i。
有解输出任意一个方案,否则输出“-1”(不含引号)。

输入描述:

输入仅一行一个整数 n(1 ≤ n ≤ 1000)。

输出描述:

如果有解,输出 n 行,每行 n 个 [1,n] 范围内的整数,第i行第j个数表示 Ai,j;否则输出"-1"。

 

示例1

输入

复制

3

输出

复制

1 3 2
2 1 3
3 2 1

 

分为一下几种情况

1.n 为 奇数

1 7 6 5 4 3 2
2 1 7 6 5 4 3
3 2 1 7 6 5 4
4 3 2 1 7 6 5
5 4 3 2 1 7 6
6 5 4 3 2 1 7
7 6 5 4 3 2 1

找规律,直接类似于于这种形式进行构造

2.n 为 2 的指数,n = 2 输出-1,否则:

先构造出n = 4 

1 2 3 4
3 4 1 2
4 3 2 1
2 1 4 3

设其为A4

A8 =      A4   (A4+4)

           (A4+4)转置 A4

1 2 3 4 5 6 7 8
3 4 1 2 7 8 5 6
4 3 2 1 8 7 6 5
2 1 4 3 6 5 8 7
6 8 7 5 1 2 3 4
5 7 8 6 3 4 1 2
8 6 5 7 4 3 2 1
7 5 6 8 2 1 4 3

A16 =  A8.....

3.n 为偶数

先找到其所对应的奇数x,不断除以2

先构造出Ax,再构造出A2x

A2x =  Ax              (Ax+x)轮换一个单位

            Ax的对称   Ax

然后 A4x =   A2x                (A2x+2x)

                      (A2x+2x)转置  A2x

例如  n = 12  x = 3

A3 =

1 3 2
2 1 3
3 2 1

A6 =

1 3 2 6 5 4
2 1 3 4 6 5
3 2 1 5 4 6
4 5 6 1 3 2
6 4 5 2 1 3
5 6 4 3 2 1

A12 =

1 3 2 6 5 4 7 9 8 12 11 10
2 1 3 4 6 5 8 7 9 10 12 11
3 2 1 5 4 6 9 8 7 11 10 12
4 5 6 1 3 2 10 11 12 7 9 8
6 4 5 2 1 3 12 10 11 8 7 9
5 6 4 3 2 1 11 12 10 9 8 7
11 12 10 9 8 7 1 3 2 6 5 4
12 10 11 8 7 9 2 1 3 4 6 5
10 11 12 7 9 8 3 2 1 5 4 6
9 8 7 11 10 12 4 5 6 1 3 2
8 7 9 10 12 11 6 4 5 2 1 3
7 9 8 12 11 10 5 6 4 3 2 1

 

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
const ll inf = 99999999999;


int fun(int x)
{
   if(x == 2 || x%2 == 1) return x;
   return fun(x/2);
}


int a[1005][1005];


int main()
{ 
   int n;
   cin >> n;
   if(n == 2) {cout << -1 << endl;return 0;}
   int fn = fun(n);
   int p;
   if(fn%2==1)
    {
       int t = fn;
       p = fn*2;
       for(int i = 1; i <= fn; i++)
	   for(int j = i+1; j <= fn; j++)
	          a[i][j] = fn-(j-i)+1;
       for(int i = 1; i <= fn; i++)
	   for(int j = 1; j <= i; j++)
	          a[i][j] = i-j+1;

       for(int i = t+1; i <= t+t; i++)
	     for(int j = t+1; j <= t+t; j++)
	           a[i][j] = a[i-t][j-t];
       for(int i = 1; i <= t; i++)
	     for(int j = t+1; j <= t+t; j++)
	          a[i][j] = a[i][max(1,(j-t+1)%(t+1))]+t;
        for(int i = t+1; i <= t+t; i++)
	     for(int j = 1; j <= t; j++)
	          a[i][j] = a[j][i-t]+t;
               
    }
   if(fn == 2)
   {
       a[1][1] = a[2][3] = a[3][4] = a[4][2] = 1;
       a[1][2] = a[2][4] = a[3][3] = a[4][1] = 2;
       a[1][3] = a[2][1] = a[3][2] = a[4][4] = 3;
       a[1][4] = a[2][2] = a[3][1] = a[4][3] = 4;
       p = 4;
   }
       for(int t = p; t < n; t*=2)
       {
	  for(int i = t+1; i <= t+t; i++)
	     for(int j = t+1; j <= t+t; j++)
	           a[i][j] = a[i-t][j-t];
          for(int i = 1; i <= t; i++)
	     for(int j = t+1; j <= t+t; j++)
	          a[i][j] = a[i][j-t]+t;
          for(int i = t+1; i <= t+t; i++)
	     for(int j = 1; j <= t; j++)
	          a[i][j] = a[t-j+1][i];
       }	  
   


   for(int i = 1; i <= n; i++)
   {
	   for(int j = 1; j < n; j++)
	   {
		   cout << a[i][j] << " ";
	   }
      cout << a[i][n] << endl;
   }
   return 0;
}


   

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值