2023NOIP A层联测25-构造

ryx 有一个非负整数 n n n。他希望你构造出一个不超过 40 × 40 40\times40 40×40 的矩阵,每个位置填 r、y、x 三者之一,使得连续的三个格子按顺序构成字符串 ryx 恰好有个。

这里连续的是指同一行、同一列或者同一45°斜线,方向任意(共 8 个方向)。

n ≤ 2222 n\le2222 n2222


先给出一种最大的构造方案

40 40
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxr
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxx
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxr
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxx
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxr
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxx
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxr
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxx
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxr
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxx
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxr
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxx
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxr
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxx
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxr
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxx
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxr
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxx
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxr
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxx
ryxyryxyryxyryxyryxyryxyryxyryxyryxyryxy

2223 2223 2223 个。

说一下构造的思路,首先先考虑最大的情况,你可能能想到把 40 40 40ryx 堆在三列,然后复制这一堆到其他的三列。把 ryx 堆在一起是较优的,有横斜两种情况。如果按上面这么做,总数是 13 × ( 40 + 38 × 2 ) = 1508 13\times(40+38\times2)=1508 13×(40+38×2)=1508,可以拿到 60pts。

然后发现 ryxryx 可以变成 ryxyr,就省出来了一列,就这样 ryxyryxyr 重复下去,总数是 19 × ( 40 + 38 × 2 ) = 2204 19\times(40+38\times2)=2204 19×(40+38×2)=2204,可以拿到 80pts。

然后你发现第 40 40 40 列是空出来的,这里也能放东西,只需 ryxyryxyr... 放下去即可,总数就是 2223 2223 2223 个,就 AC 了。

对于精确为 n n n 的做法,可以先放整列,然后对于散的 n n n 就模拟一个一个放就可以了。可以看代码实现。

#include
using namespace std;
int n;
char a[41][41];
int main()
{
    freopen("ryx.in","r",stdin);
    freopen("ryx.out","w",stdout);
    cin>>n;
    int czn=n/116;
    for(int i=1;i<=40;i++) a[i][1]='r';
    for(int i=1;i<=czn;i++){
        for(int j=1;j<=40;j++){
            a[j][i*2]='y';
            a[j][i*2+1]=i&1?'x':'r';
        }
    }
    int x=2+czn*2;
    if(n<=2204){
        n-=czn*116;
        if(!n) goto a;
        if(n==1){
            a[1][40]='r',a[2][40]='y',a[3][40]='x';
            goto a;
        }
        if(n==2){
            a[1][40]='r',a[2][40]='y',a[3][40]='x',a[4][40]='y',a[5][40]='r';
            goto a;
        }
        a[1][x]='y',a[1][x+1]=(czn&1?'r':'x');
        a[2][x]='y',a[2][x+1]=(czn&1?'r':'x');
        a[3][x]='r';
        n-=3;
        int y=3;
        while(n){
            if(n==1){
                a[1][40]='r',a[2][40]='y',a[3][40]='x';
                goto a;
            }
            else if(n==2){
                a[1][40]='r',a[2][40]='y',a[3][40]='x',a[4][40]='y',a[5][40]='r';
                goto a;
            }
            else a[y][x]='y',a[y][x+1]=(czn&1?'r':'x'),n-=3,y++;
            a[y][x]='r';
        }
    }
    else{
        n-=2204;
        int x=2,cnt=1;
        a[x][40]='r';
        while(n--){
            a[x+1][40]='y';
            a[x+2][40]=cnt&1?'x':'r';
            x+=2;
            cnt++;
        }
    }
    a:for(int i=1;i<=40;i++) for(int j=1;j<=40;j++) if(!a[i][j]) a[i][j]='y';
    cout<<"40 40\n";
    for(int i=1;i<=40;i++){
        for(int j=1;j<=40;j++) cout<<a[i][j];
        cout<<'\n';
    }
}

你可能感兴趣的:(c++)