从CF1737学习区间计数处理与开方精度丢失问题

Problem - B - Codeforces

思路出来之后,需要计算 l,r 区间的个数。

我想的是计算出 [0,r] 的个数和 [0,l] 的个数,然后相减。

大体上是没问题,但是我的实现麻烦而且有错误。

1|0初始代码

void solve() { ll l, r; cin >> l >> r; auto calc = [&](ll x, bool opt) { if (x == 1) return opt ? 0LL : 1LL; ll SQRT = sqrtl(x); if (SQRT * SQRT == x) return opt ? (SQRT - 1 << 1) + SQRT - 1 : (SQRT - 1 << 1) + SQRT; SQRT++; ll cmp = SQRT * SQRT; if (opt) { if (x > cmp - 1) return (SQRT - 1 << 1) + SQRT - 1; if (x == cmp - 1) return (SQRT - 1 << 1) + SQRT - 1 - 1; if (x > cmp - SQRT) return (SQRT - 1 << 1) + SQRT - 2; if (x == cmp - SQRT) return (SQRT - 1 << 1) + SQRT - 2 - 1; return (SQRT - 1 << 1) + SQRT - 3; } if (x >= cmp - 1) return (SQRT - 1 << 1) + SQRT - 1; if (x >= cmp - SQRT) return (SQRT - 1 << 1) + SQRT - 2; return (SQRT - 1 << 1) + SQRT - 3; }; cout << calc(r, 0) - calc(l, 1) << endl; }
  • 万一左端点 l 是有效值,减去的时候会计算进去,从而让答案少 1,而不是有效值的话又不会影响答案,所以在 calc 上加了很麻烦特判。
    • 实际上这类问题可以求 [0,l1] 的个数,然后再用 [0,r] 来减即可,完美避免了上述问题。
  • sqrtlong long 开方会丢精度!
    • sqrtl

2|0改进代码

void solve() { ll l, r; cin >> l >> r; auto calc = [&](ll x) { if (x == 0) return 0LL; if (x == 1) return 1LL; ll SQRT = sqrtl(x); if (SQRT * SQRT == x) return (SQRT - 1 << 1) + SQRT; SQRT++; ll cmp = SQRT * SQRT; if (x >= cmp - 1) return (SQRT - 1 << 1) + (SQRT - 1); if (x >= cmp - SQRT) return (SQRT - 1 << 1) - 1 + (SQRT - 1); return (SQRT - 2 << 1) + SQRT - 1; }; cout << calc(r) - calc(l - 1) << endl; }

__EOF__

本文作者Kdlyh
本文链接https://www.cnblogs.com/kdlyh/p/18001481.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   加固文明幻景  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示