题目描述
有 n 个正整数 a1 ,… ,an ,将它们联接成一排,相邻数字首尾相接,组成一个最大的整数。
原题链接
https://www.luogu.com.cn/problem/P1012
正解
将数组按“正确比较方式”进行从大到小排序,再依次输出。
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
string s[20000];int n;
bool cmp(const string &a,const string &b) { // &表示引用
return (a+b > b+a);
}
int main(void) {
cin >> n;
for(int i=1;i<=n;++i) cin >> s[i];
sort(s+1,s+n+1,cmp);
for (int i=1;i<=n;++i) cout << s[i];
return 0;
}
证明
“正确比较方式”: 字符串A,B,将A、B进行首尾拼接计AB,将B、A进行首尾拼接计BA,
如果AB的字典序大于BA的字典序,那么计 A 》 B ,即排序时候A在B前面
反之AB的字典序小于BA的字典序,那么计 A 《 B ,即排序时候B在A前面
如果AB的字典序等于BA的字典序,那么计 A = B
正解的数组满足: 第一个数 》= 第二个数 》= 第三个数 》=…》= 第N个数
因为如果存在 2个相邻的数之间,不满足》=关系,那么这2个数交换,就会得到更大的结果
现在只需要证明》= 具有传递性 即 如果 A》=B,B》=C 那么 A》=C
设a,b 为字符串A、B代表的数字,len(a),len(b) 为a、b的位数,如len(123) = 3 、 len(9) = 1;
A》= B,B》= C,有:
a × \times × 1 0 l e n ( b ) 10^{len(b)} 10len(b) + b >= b × \times × 1 0 l e n ( a ) 10^{len(a)} 10len(a)+ a
即a × \times × 1 0 l e n ( b ) 10^{len(b)} 10len(b) - a >= b × \times × 1 0 l e n ( a ) 10^{len(a)} 10len(a) - b
即a × \times × ( 1 0 l e n ( b ) 10^{len(b)} 10len(b)-1) >= b × \times × ( 1 0 l e n ( a ) 10^{len(a)} 10len(a) - 1)
即 a b \frac{a}{b} ba >= 1 0 l e n ( a ) − 1 1 0 l e n ( b ) − 1 \frac{10^{len(a)} - 1}{10^{len(b)} - 1} 10len(b)−110len(a)−1
同理由b × \times × 1 0 l e n ( c ) 10^{len(c)} 10len(c) + c >= c × \times × 1 0 l e n ( b ) 10^{len(b)} 10len(b)+ b
有: b c \frac{b}{c} cb >= 1 0 l e n ( b ) − 1 1 0 l e n ( c ) − 1 \frac{10^{len(b)} - 1}{10^{len(c)} - 1} 10len(c)−110len(b)−1
两式相乘得 a c \frac{a}{c} ca >= 1 0 l e n ( a ) − 1 1 0 l e n ( c ) − 1 \frac{10^{len(a)} - 1}{10^{len(c)} - 1} 10len(c)−110len(a)−1
即A》= C, 传递性得证