题意
给出 $n$ 和 $l$,要你构造 $3n$ 个长度为 $l$ 字符串,使得字符串都是由 0,1,2
组成且字符串两两不同,每个字符在每个字符串的同一位的出现次数都是 $n$ 次。
要你最小化你构造出来的字典序最大的字符串的字典序,输出 $3n$ 个字符串。
题解
我们可以将 $3n$ 个字符串分为0开头的,1开头的,2开头的。对于前两种字符串,它们的字典序显然不是最大的,因此既然要求最大字典序最小,我们就要考虑构造2开头的字符串,使得其最大字典序最小。
我们可以这样按照3进制下的 $[0,n)$ 贪心构造出 $n$ 个字符串,即可满足最小:
200...00000
200...00001
200...00002
200...00010
200...00011
200...00012
200...00020
...
而对于1开头和0开头的字符串,我们直接从2开头的置换而来即可。
#include<iostream>
using namespace std;
const int maxn=50010,maxl=20;
int n,l,a[maxn][maxl],b[maxn][maxl],c[maxn][maxl];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>l;a[1][1]=2;
for(int i=2;i<=n;i++){
for(int j=1;j<=l;j++)a[i][j]=a[i-1][j];
int k=l;
a[i][l]++;
while(k>1){
if(a[i][k]>2)a[i][k]=0,a[i][--k]++;
else break;
}
}//3进制贪心求n个2开头的字符串
for(int i=1;i<=n;i++){
for(int j=1;j<=l;j++)b[i][j]=(a[i][j]+1)%3;
for(int j=1;j<=l;j++)c[i][j]=(a[i][j]+2)%3;//根据2开头的置换
}
for(int i=1;i<=n;i++){
for(int j=1;j<=l;j++)cout<<a[i][j];
cout<<'\n';
}
for(int i=1;i<=n;i++){
for(int j=1;j<=l;j++)cout<<b[i][j];
cout<<'\n';
}
for(int i=1;i<=n;i++){
for(int j=1;j<=l;j++)cout<<c[i][j];
cout<<'\n';
}
return 0;
}