题解:P15022 [UOI 2020 II Stage] 邻居

· · 题解

这是一道非常简单的小学数学问题。

鉴于红题题解是给小 oier 们看的。

所以要难以理解通俗易懂。

#

首先观察样例。

主对角线即黄色方块,我们尝试找一下规律,可以发现它们的公差为 5,即是 n+1

相应的副对角线上数字的公差为 3,即是 n-1

接下来是代码。

#

最开始的错误代码

#include<bits/stdc++.h>
#define int long long 
#define fast register int 

using namespace std;

const int N=1e4+100;

int n,m;

int a[N],b[N];//a数组用来表示是否是主对角线数字 b数组则表示副对角线

signed main(){
    std::ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);

    cin>>n>>m;

    for (fast i=1;i<=n*n;i++){
        if ((i-1)%(n+1)==0) a[i]=1;//这里给主对角线判断
        if ((i-n)%(n-1)==0) b[i]=1;//这里给副对角线判断
    }

    if (a[m]==1) cout<<"yes ";//判断一下m是否在主对角线上
    else cout<<"no ";//否则输出no

    if (b[m]==1) cout<<"yes";//是否在副对角线上
    else cout<<"no";//否则输出no

    return 0;
}

你看出来问题了吗?

问题在于

if ((i-1)%(n+1)==0) a[i]=1;//这里给主对角线判断

if ((i-n)%(n-1)==0) b[i]=1;//这里给副对角线判断

注意到样例。

4 开始时,一直加下去,如果没有边界,会导致它加到 16,使得 16 变成副对角线上的数字。

n=1 时,会导致模除以 0,是不合理的。

很明显,这是错误的。

于是进一步修改

#include<bits/stdc++.h>
#define int long long 
#define fast register int 

using namespace std;

const int N=2e5+100;

int n,m;

int a[N],b[N];

signed main(){
    std::ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);

    cin>>n>>m;

    for (fast i=1,j=1;i<=n;j+=n+1,i++){//i表示次数 每次只能加到n次 j表示第i个的主对角线数
        a[j]=1;
    }

    for (fast i=1,j=n;i<=n;j+=n-1,i++){//i表示次数 每次只能加到n次 j表示第i个的副对角线数
        b[j]=1;
    }

    if (a[m]==1) cout<<"yes ";
    if (a[m]==0) cout<<"no ";

    if (b[m]==1) cout<<"yes";
    if (b[m]==0) cout<<"no";

    return 0;
}