AtCoder Beginner Contest 268 F Best Concatenation

Best Concatenation#

贪心 - 相邻交换

考虑两个相邻位置的元素,如果进行交换,会对答案造成怎样的影响

假设现有一个排列,我们拿出其中两个相邻项 AB

考虑 ...+A+B+......+B+A+... 的顺序对答案造成了什么影响

假设单独一个 AB 的贡献为 ansAansB

ABX 的数量为 XAXB

AB 的数字之和为 cntAcntB

显然不管 AB 如何排列,对其前后的答案影响是相同的,于是直接消去

  1. A+B

答案贡献为:ansA+ansB+cntBXA

  1. B+A

答案贡献为:ansA+ansB+cntAXB

因此两者相互消去 ansA+ansB 后,为

cntBXAcntAXB 之间的比较

我们想用排序来完成这项比较的工作就必须证明其偏序的传递性

可以让左右两边同时除以 cntBcntA

那么就有 XAcntAXBcntB 之间的比较

因为其值都与本身的属性有关,都是自身的值,因此显然有传递性

由于整除等原因,直接用 cntBXAcntAXB 这个的大小关系进行比较即可

之前牛客多校也碰到了此类题目,一直觉得是队友瞎搞,这次题目才开始想看看到底是个啥,发现其实推个式子,化简完之后证明传递性都是很简单的

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
ll x[maxn], num[maxn], mp[maxn];
string s[maxn];

inline bool cmp(int a, int b)
{
    return x[a] * num[b] > x[b] * num[a];
}

int main()
{
    int n;
    cin >> n;
    for(int i=0; i<n; i++)
    {
        cin >> s[i];
        for(char now : s[i])
        {
            if(now == 'X') x[i]++;
            else num[i] += now - '0';
        }
        mp[i] = i;
    }
    sort(mp, mp + n, cmp);
    ll ans = 0, sum = 0;
    for(int i=n-1; i>=0; i--)
    {
        for(int j=s[mp[i]].length() - 1; j>=0; j--)
        {
            if(s[mp[i]][j] == 'X') ans += sum;
            else sum += s[mp[i]][j] - '0';
        }
    }
    cout << ans << endl;
    return 0;
}
posted @   dgsvygd  阅读(59)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示
主题色彩