模拟赛 c7-C table

题目描述

需要生成 \(3N\) 个长度为 \(L\) 的字符串,字符仅包含 0,1,2,构成 \(3N\) 行 \(L\) 列表格,满足两个条件:

  1. 所有 \(3N\) 个字符串两两互不相同;
  2. 表格每一列,字符 0、1、2 恰好各出现 \(N\) 次。

在满足条件前提下,要求整张表字典序最大的字符串尽可能小;输出任意一种最优构造方案。

字典序规则:\((0<1<2)\),逐位比较,第一位不同则判定大小。

输入格式

一行两个整数 \((N,L)\)

输出格式

输出 \(3N\) 行,每行一个长度为 \(L\)、仅含 0/1/2 的字符串。

样例输入 1

1 2

样例输出 1

01
12
20

样例解释

共 3 个字符串,每一列:

第 1 列:0,1,2;第 2 列:1,2,0;每类字符各出现 1 次。

样例输入 2

2 2

样例输出 2

01
10
02
20
12
21

样例解释

对于样例1:

输出了3个长度为2的字符串。第一列是0,1,2,第二列是1,2,0,每一列中的0、1、2都各出现一次。

数据范围

对于30%的数据,保证\(N=1\)。

对于100%的数据,保证\(1\le N \le 5\times 10^4,\ 1\le L \le 15,且 \ 3N \le 3^L\)。

算法分析

要每个字符串都不一样,而且要最大的字符串的字典序最小,那么以1和0开头的字符串就不用考虑了,因为以2开头的字符串的字典序更大,因为所有字符串要不相等,那么不难想到以2开头的字符串后面接的都是有前导零、以0开始依次递增的三进制数,以2开头的处理完后,剩下的以1和0开头的字符串就是用来把数量填上的。代码很简单。

AC代码

#include<bits/stdc++.h>
using namespace std;
int n,l;
string sjz(int x,int len){//生成三进制数
    string s = "";
    for(int i = 1; i<=len; i++){
        s+="0";//加"0"
    }
    for(int i = len-1; i>=0; i--){//三进制数
        s[i] = char('0'+x%3);
        x/=3;
    }
    return s;
}
int main(){
    cin>>n>>l;
    for(int i = 0; i<n; i++){
        string s = "2"+sjz(i,l-1);//以2开头的字符串
        for(int j = 0; j<3; j++){
            string t = s;//copy一份
            for(char &k : t){
                k = char('0'+(k-'0'+j)%3);//把剩下的字符串填上
            }
            cout<<t<<'\n';//依次输出
        }
    }
    return 0;
}

总结

这道题总的来说还是有点难度的,主要是思路有一点难想,很难证明正确性,但代码还是相对好写的,只是需要注意前导零和字符串不能相等,其他都好写,个人认为可以给黄到绿,算难的黄题或简单的绿题。

posted @ 2026-08-17 11:03  xmgene  阅读(16)  评论(0)    收藏  举报