P9837 题解

奇怪的构造方法居然过了...

本构造方法暂无证明,只是提供一种乱搞做法。

对于奇数的情况

首先我们从样例入手(为 5 的情况):

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

然后我们对样例进行一点改造:

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

我们将这个数组水平翻转一下,再顺时针旋转 45 度:

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

然后就使用瞪眼法,发现偶数行和奇数行规律不同,将它们分离成两部分:

5
4 5 3
1 3 5 4 2

3 4
2 1 2 1

我们发现奇数行的最后一行是 1 3 5 4 2 ,按照奇偶再分成两部分:1 3 54 2

然后我们发现最后一行先是 1n 的奇数,再是 n12 的偶数。

然后我们再看倒数第二行 4 5 3 和最后一行去除头尾元素的部分 3 5 4

发现倒数第二行只是把最后一行去除头尾元素的部分翻转了。

然后依照该规律向上构造即可。


再看偶行,由下到上就是从小到大的相邻的两个数反复出现而已。

从上到下先是奇数开头,再是偶数开头。

对于偶数的情况

偶数的样例只能自己手搓一个(为 6 的情况):

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

和奇数一样,将这个数组水平翻转一下,再顺时针旋转 45 度:

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

然后将奇偶行分离:

6
3 4 3
2 1 2 1 2

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

奇数行和另一种情况的偶数行构造一致。

只是从上到下先是偶数开头,再是奇数开头。


不难发现偶数行是对称的。

最后一行的前半部分是 1 3 5 ,倒数第二行的前半部分是 4 6

然后我们发现最后一行是 1n1 的奇数,倒数第二行是 2n 的偶数。

两组数据交替出现。

每次向上构造时删除头尾元素即可。

Code

#include<bits/stdc++.h>
using namespace std;
#define maxn 4003
int mp[maxn][maxn];
int ls[maxn];
int ls1[maxn], ls2[maxn];
void solve1(int n)
{
for(int i=1;i<=n;i++) ls[i]=(i<=(n>>1)+1)?(i<<1)-1:(n-i+1)<<1;
int cnt1=0;
for(int i=1;i<=n;i++)
{
if(i&1)
{
cnt1++;
int mf=cnt1;
if(i&2) for(int j=i;j<=n;j++)
mp[n-j+i][n-j+1]=ls[mf++];
else for(int j=i;j<=n;j++)
mp[j][j-i+1]=ls[mf++];
}
else
{
if(i&2)
{
int st=i-2;
for(int j=i;j<=n;j++)
mp[j][j-i+1]=(st^=1)+1;
}
else
{
int st=i-1;
for(int j=i;j<=n;j++)
mp[j][j-i+1]=(st^=1)+1;
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
cout<<mp[i][j]<<' ';
cout<<'\n';
}
}
void solve2(int n)
{
for(int i=1;i<=n>>1;i++) ls1[i]=(i<<1)-1;
for(int i=1;i<=n>>1;i++) ls2[i]=(i<<1);
for(int i=(n>>1)+1;i<=n;i++) ls1[i]=((n-i+1)<<1)-1;
for(int i=(n>>1)+1;i<=n;i++) ls2[i]=((n-i+1)<<1);
int cnt1=0;
for(int i=1;i<=n;i++)
{
if(i&1)
{
cnt1++;
int mf=cnt1;
if(i&2) for(int j=i;j<=n;++j)
mp[n-j+i][n-j+1]=ls2[mf++];
else for(int j=i;j<=n;++j)
mp[j][j-i+1]=ls1[mf++];
}
else
{
if(i&2)
{
int st=i-2;
for(int j=i;j<=n;++j)
mp[j][j-i+1]=(st^=1)+1;
}
else
{
int st=i-1;
for(int j=i;j<=n;++j)
mp[j][j-i+1]=(st^=1)+1;
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
cout<<mp[i][j]<<' ';
cout<<'\n';
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int n,w;
cin>>n>>w;
if(n&1) return solve1(n), 0;
else return solve2(n), 0;
}

本文作者:redacted-area

本文链接:https://www.cnblogs.com/redacted-area/p/18379517

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Jimmy-LEEE  阅读(4)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起