题解 CF1361B Johnny and Grandmaster

目前(洛谷)最优解写法。

首先将 ki 降序排列,并将相同的 ki 合并。由于每个式子都是形如 pki 的形式,即底数相同,可以考虑变成 p 进制,发现对于任意 c1,,ci+1a0<a1<a2<ai+1,满足 ci+1×pai+1j=1icj×paj 时,ci+1×pai+1j=1icj×paj 一定被 pa0 整除。

我们可以考虑记录 s1,s2 表示两堆的和,使任意时刻 s1<s2
考虑 ki 降序排序时贪心用较大的 k 补足 s2s1now 当前到 i,且 pki×now=s2s1。由于是降序排序,如果 now>n 那么后面的 k 都一定分配到 s1。否则先使 s1=s2,再用剩下的 ki 分配给 s1,s2,注意满足 s1<s2

Code

def(N, int, 1e6 + 5) def(p, int, 1e9 + 7) int n, m; int k[N]; int main() { int t; qread(t); W(t) { qread(n, m); rep(i, 1, n) qread(k[i]); sort(k + 1, k + n + 1, greater<int>()); ll nw = 0; ll s1 = 0, s2 = 0; rep(i, 1, n) { if(nw && m != 1 && i != 1) { int nwm = k[i - 1] - k[i]; rep(j, 1, nwm) { nw *= m; if(nw > n) { rep(l, i, n) s1 = (s1 + qpow(k[l], m, p)) % p; goto End; } } } int cn = 0, j = i; while(j <= n && k[i] == k[j]) ++j, ++cn; int ps = min(nw, (ll)cn); nw -= ps; if(cn > ps) { cn -= ps; int c1 = cn >> 1, c2 = cn - c1; if(c1 != c2) nw = 1; s1 = qpow(k[i], m, p) * c1 % p; s2 = qpow(k[i], m, p) * c2 % p; } else s1 = (s1 + qpow(k[i], m, p) * cn % p) % p; i = j - 1; // cout << s1 << ' ' << s2 << endl; } End:; printf("%lld\n", (s2 - s1 + p) % p); } return 0; }

__EOF__

本文作者BreezeEnder
本文链接https://www.cnblogs.com/BreezeEnder/p/15780357.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   BreezeEnder  阅读(43)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 趁着过年的时候手搓了一个低代码框架
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· 乌龟冬眠箱湿度监控系统和AI辅助建议功能的实现
点击右上角即可分享
微信分享提示