给定 X 和数字构成的字符串,你需要对其进行排列并拼接成新的字符串 X 的数量,并求和。输出分数最大值。
首先一个显然的结论即为对于题目定义的分数,同一字符串内部的 X 对其数字的贡献,与字符串在排列中的顺序无关。
于是我们考虑其它字符串的 X 对字符串数字的贡献,我们考虑字符串 X 的数目,令
则不难想到若我们要将
所以我们直接考虑对字符串进行排序,比较规则则按照刚才的式子跑一下即可。
同时我们也可以从意义上感性理解,显然只有前面的 X 对后面的数字产生贡献,所以我们将 X 更多数字更少的放在前面,则
同时对于此贪心的证明,考虑若满足偏序关系
存在双倍经验 LG-P1080 [NOIP2012 提高组] 国王游戏。
xxxxxxxxxx61123
45678910
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 初稿