给定 X
和数字构成的字符串,你需要对其进行排列并拼接成新的字符串 X
的数量,并求和。输出分数最大值。
首先一个显然的结论即为对于题目定义的分数,同一字符串内部的 X
对其数字的贡献,与字符串在排列中的顺序无关。
于是我们考虑其它字符串的 X
对字符串数字的贡献,我们考虑字符串 X
的数目,令
则不难想到若我们要将
所以我们直接考虑对字符串进行排序,比较规则则按照刚才的式子跑一下即可。
同时我们也可以从意义上感性理解,显然只有前面的 X
对后面的数字产生贡献,所以我们将 X
更多数字更少的放在前面,则
同时对于此贪心的证明,考虑若满足偏序关系
存在双倍经验 LG-P1080 [NOIP2012 提高组] 国王游戏。
xxxxxxxxxx
611
2
3
4
5
6
7
8
9
10
11using namespace std;
12
13mt19937 rnd(random_device{}());
14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
15bool rnddd(int x){return rndd(1, 100) <= x;}
16
17typedef unsigned int uint;
18typedef unsigned long long unll;
19typedef long long ll;
20typedef long double ld;
21
22template < typename T = int >
23inline T read(void);
24
25int N;
26struct Node{string S; int sum, cnt;}d[210000];
27ll ans(0);
28
29int main(){
30 N = read();
31 for(int i = 1; i <= N; ++i){
32 cin >> d[i].S;
33 for(auto c : d[i].S)
34 if(c == 'X')++d[i].cnt;
35 else d[i].sum += c - '0';
36 }sort(d + 1, d + N + 1, [](const Node &a, const Node &b)->bool{return (ll)a.sum * b.cnt < (ll)b.sum * a.cnt;});
37 ll cur(0);
38 for(int i = 1; i <= N; ++i)
39 for(auto c : d[i].S)
40 if(c == 'X')++cur;
41 else ans += cur * (c - '0');
42 printf("%lld\n", ans);
43 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
44 return 0;
45}
46
47template < typename T >
48inline T read(void){
49 T ret(0);
50 int flag(1);
51 char c = getchar();
52 while(c != '-' && !isdigit(c))c = getchar();
53 if(c == '-')flag = -1, c = getchar();
54 while(isdigit(c)){
55 ret *= 10;
56 ret += int(c - '0');
57 c = getchar();
58 }
59 ret *= flag;
60 return ret;
61}
update-2023_01_18 初稿