模拟赛 c7-C table
题目描述
需要生成 \(3N\) 个长度为 \(L\) 的字符串,字符仅包含 0,1,2,构成 \(3N\) 行 \(L\) 列表格,满足两个条件:
- 所有 \(3N\) 个字符串两两互不相同;
- 表格每一列,字符
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;
}
总结
这道题总的来说还是有点难度的,主要是思路有一点难想,很难证明正确性,但代码还是相对好写的,只是需要注意前导零和字符串不能相等,其他都好写,个人认为可以给黄到绿,算难的黄题或简单的绿题。

浙公网安备 33010602011771号