惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
Security Latest
Security Latest
C
Cisco Blogs
P
Palo Alto Networks Blog
Know Your Adversary
Know Your Adversary
Project Zero
Project Zero
C
Cyber Attacks, Cyber Crime and Cyber Security
NISL@THU
NISL@THU
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Secure Thoughts
P
Privacy International News Feed
V
Vulnerabilities – Threatpost
D
Docker
Google Online Security Blog
Google Online Security Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Recent Announcements
Recent Announcements
T
The Exploit Database - CXSecurity.com
G
Google Developers Blog
Schneier on Security
Schneier on Security
小众软件
小众软件
爱范儿
爱范儿
GbyAI
GbyAI
J
Java Code Geeks
T
Tailwind CSS Blog
Cisco Talos Blog
Cisco Talos Blog
The Hacker News
The Hacker News
D
DataBreaches.Net
Blog — PlanetScale
Blog — PlanetScale
TaoSecurity Blog
TaoSecurity Blog
MyScale Blog
MyScale Blog
B
Blog RSS Feed
Cyberwarzone
Cyberwarzone
有赞技术团队
有赞技术团队
Martin Fowler
Martin Fowler
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
Securelist
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Y
Y Combinator Blog
S
Schneier on Security
Latest news
Latest news
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 叶小钗
F
Fortinet All Blogs
M
MIT News - Artificial intelligence
PCI Perspectives
PCI Perspectives
V
V2EX
V2EX - 技术
V2EX - 技术
O
OpenAI News
W
WeLiveSecurity

皓子的小站

网站字体应用之坑——font-family 篇 糟糕的 meta name="theme-color" How to Automatically Track Newly Supported ESLint Rules in Oxlint How to Gradually Migrate from ESLint to Oxlint (Without Breaking Everything) 静态资源预压缩:零运行时开销,极致节省带宽 CVE-2025-70886 Proof of Concept (PoC) | A Script to Crash Halo CMS Comment Backend 自定义网页鼠标指针——一段曲折的旅程 CVE-2025-70886 漏洞复现/PoC | 一个脚本让 Halo CMS 评论后台瘫痪 2025 年终总结 & 博客两周年 老用户专享!已有 Halo 专业版授权可免费升级商业版 自动追踪 Oxlint 对 ESLint 规则的新增支持 Halo 贡献者证书与实体周边盲盒开箱 博客评论系统指南 CDN 回源跟随配置导致登录异常问题排查 SCDN 免费赞助计划:助力高质量博客&博客圈 锐捷校园网:网络共享与带宽叠加方案(哈理工案例) ESLint 到 Oxlint 渐进式迁移快速上手指南 Fixing Vite Breaking Inline JS & CSS in Thymeleaf Templates 解决 Vite 破坏 Thymeleaf 模板内联 JS & CSS 的方法 我的博客,为什么是月更? 博客俱乐部一周年纪念品开箱 网站字体加载之坑——format 篇 经历 1000000000 次 DDoS 请求攻击后,我总结了三条经验 题解分享:[蓝桥杯 2025 国 Python A] 杨辉三角 P12876 FiF口语训练破解刷分教程(适用于 Windows) 不要与蠢人辩论 小心网络地雷·续篇 当心网络组织“开往”·续篇 当心网络组织“开往” 小心网络地雷 在 Halo CMS 中通过模板实现随机推荐多篇文章 回应某博客上有关“开往”组织在内部会议上对我的污蔑(上) 再遭 DDoS 攻击:CDN 流量限额拦不住请求计费飙升 2025年团体程序设计天梯赛 - Python 个人赛时暴力题解 网站流量分析工具 Umami 中国大陆合规版发布 把握当下,享受生活 Folo 认证功能反成漏洞?警惕 RSS 订阅源所有权被恶意盗取风险 在 Halo CMS 中通过模板实现随机文章跳转功能 从沉默展柜到时代回响:731部队罪证陈列馆参访手记 脚本分享:CDN 流量触顶后自动切换至 Cloudflare 官方 BUG 快薅!Halo 永久/买断用户可额外获得一份买断许可 老用户专享!已有 1Panel 永久授权/买断许可用户可再领免费买断许可证! 限时特惠!1¥ 立即解锁 1Panel 专业版全功能 61 天 混合云架构下的动态 IPv6 智能加速实践:从家庭网络到全球分发的低成本部署指南 如何用 AI 全方面辅助博客创作 - 从博文之内到博文之外 Random Number Generation and Formatting in Thymeleaf Thymeleaf 随机数生成与格式化详解 列举我维护的项目和发布的软件包 快速部署教程 - 通过 Webhook 触发邮件通知的开源自托管服务 Going Against the Grain - Four Websites That Make Your URL Longer 反其道而行 - 四个让你网址变得更长的网站 2024 年终总结 & 博客一周年 基于 OneBot API 的简易异步 QQ 群批量发消息脚本 如何快速完成中文排版优化 如何给文章分类和打标签 群规之敏感违禁词对抗 一图展示​ ​RSS3 世界 - The Open(RSS3) Universe 开源项目发到 bilibili 后可能获得的 PR C/C++:为什么 a[i][j] 等价于 *(*(a+i)+j) Fast Methods to Convert Uppercase Letters to Lowercase in C++ C++ 中快速将字符串大写字母转为小写的方法 Fixing GitHub Actions push to ghcr '403 Forbidden' error Fixing docker pull image "ghcr.io..." Unauthorized error 本站“算法题练习/题解分享”相关文章汇总 不怕流氓多,就怕流氓有文化——站长应该防范的几个问题及对应解决方法分享 题解分享:HRBUST 1132 水数 新手程序员必备的三项技能 如何快速排查插件(模组)的兼容性问题(基于二分法和分治思想) 通过 Umami 最新功能观察定时发布文章的最佳时段 踩坑分享:如何一个人搬运 126.7 斤的书坐动车 两篇文章分享:别像弱智一样提问 & 提问的智慧 论下落式音游/定轨音游中的优质粪铺(文末附铺面推荐) 为什么选择无纸化阅读?为什么买墨水屏电子书?为什么 Kindle“失败”了? 我维护的 Halo 主题,现已发布到 Halo 应用商店! OSU!Standard(osu!std)/OSU!Taiko 转 OSU!Mania 铺面转换器发布 我常用的 OSU!Mania 皮肤分享 电荷守恒辨析:为什么一个离子带多个电荷要乘上所带电荷数而不是除以所带电荷数 注意!align-items: flex-start 会导致 overflow-wrap: break-word 失效 惊人 98 元限定T恤!1Panel, Halo 开发商开启推广积分奖励活动 Minecraft Spigot Bukkit 服务器插件开发 教程收集 中文博客倡议 Windows 10 遇到“只能重装系统”但不想重装的解决方案 Windows 10 文件系统错误 -2144926975 -2147219196 修复 Windows 10 升级 Windows 11 简明教程 CSS 预处理器如何正确的复用样式(stylus 中使用 @extend 继承的坑) 请一定要回复博客下的匿名评论!对于博主和评论者有关匿名评论的倡议 一图解释单一质点运动波动图像和振动图像的关系 解决 Docker pull image "ghcr.io..." Unauthorized error 解决 GitHub Actions push to ghcr '403 Forbidden' error 解决 Umami API 更新延迟问题(如何修改开源项目代码并构建 Docker 镜像-以 Umami 为例) 在国家公祭日自动将网站变灰 中文博客圈列表 解决 Halo CMS 的 Umami Plugin CORS&CSP 跨域报错问题 Windows 创建存储池报错 无法创建池 不支持该请求 (0x00000032) Windows 显示器突然黑白 桌面突然黑白 鼠标和截图还是彩色的 通过指令过滤出正确的公网 IPv6 地址(记一次折腾 IPv6 DDNS) 我的世界免费科技地址 1.7-1.21 网站 Favicon 下载工具发布 键盘 Bios 内可用 系统内无法输入 设备管理器无黄色感叹号 设备管理器 网卡一堆黄色感叹号 例如 WAN, Miniport
题解分享:[AtCoder Beginner Contest 414 E] Count A%B=C
HowieHz · 2025-07-13 · via 皓子的小站

题目链接:E - Count A%B=C
首发:题解:AT_abc414_e [ABC414E] Count A%B=C - 洛谷专栏
相关知识点:数论分块 - OI Wiki
附录:尝试做了做 100 分钟只能出 ABCE 题。还得多多努力,看大佬 40 分钟除了 G 都出了。
20250731 更新:补充了 C++ 实现。

题目简述

给定正整数 N,统计满足以下条件的三元组 (a, b, c) 的个数:

  • 1 \leq a, b, c \leq N
  • a, b, c 两两不同
  • a \bmod b = c

输出方案数对 998244353 取模。

分析题目

对于每一组 (a, b)c = a \bmod b 唯一确定。
但三元组需满足两两不同,且 c \in [1, N]

所以完成以下三步

  1. 确定 b 的范围。
  2. 对于每一个 b,计算满足条件的 a 的取值个数。
  3. 枚举所有可能的 b,将每个 b 对应的合法 a 的取值个数累加,最后对答案取模后输出。

解题思路

确定 b 的范围

由于题目要求 a,b,c 两两不同,我们容易想到可以对 a,b 大小关系进行分类讨论:

  • a < ba \bmod b = a,此时 c = a,不符“两两不同”,排除。
  • a > ba \bmod b = c,此时 N \geq a > b > c \geq 0,三者必然不同。

因此,只需考虑 a > b 的情况,N \geq a > b > c \geq 0 的情况

N \geq a > b > c \geq 0 与题目限制 c \geq 1,可得 b 的取值范围为 [2,N-1]

计算满足条件的 a 的取值个数

N \geq a > b > c \geq 0 可得:对于每个 ba 的取值范围为 [b+1, N],共 N-b 个。

但还需满足 c = a \bmod b \geq 1,即 a 不是 b 的倍数(否则 c=0 不合法)。

a 的取值范围 [b+1, N] 内,ab 的倍数的情况可以用等式表示:

a = k \times b ( k \in \mathbb{Z},\ 2 \leq k \leq \left\lfloor \frac{N}{b} \right\rfloor)

注释:因为 a > b 所以 k \neq 1

从上诉等式可知,a 可以取的倍数个数为 k \in [2,\lfloor \frac{N}{b}\rfloor]
即,ab 的倍数的个数为 \left\lfloor \frac{N}{b} \right\rfloor - 1

因此,对于每个 b,合法 a 的个数为:

(N-b) - (\left\lfloor \frac{N}{b} \right\rfloor - 1)

(N-b+1) - \left\lfloor \frac{N}{b} \right\rfloor

最终累加

综上所述,我们只需枚举 b 的所有可能取值 2 \leq b \leq N-1,对于每个 b,将其对应的合法 a 的个数 (N-b+1) - \left\lfloor \frac{N}{b} \right\rfloor 累加起来。

因此,答案可以表示为如下求和公式:

\sum_{b=2}^{N-1} \left[ (N-b+1) - \left\lfloor \frac{N}{b} \right\rfloor \right]

最后,将结果对 998244353 取模后输出即可。

代码实现

Python 3 实现:

n = int(input())
mod = 998244353

ans = 0
for b in range(2, n):  # 2 <= b <= n-1
    ans += (n-b+1) - n//b
print(ans % mod)

C++ 实现:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const ll mod = 998244353;

int main() {
    ll n;
    cin >> n;

    ll ans = 0;
    for (ll b = 2; b < n; b++) {  // 2 <= b <= n-1
        ans = (ans + (n - b + 1) % mod + mod - (n / b) % mod) % mod;
    }

    cout << ans << endl;
    return 0;
}

复杂度分析

时间复杂度 O(N),题目 N 范围 3 \leq N \leq 10^{12},显然会超时。

优化:数论分块

分析求和公式

\begin{align*} &\sum_{b=2}^{N-1} \left[ (N-b+1) - \left\lfloor \frac{N}{b} \right\rfloor \right] \\ &= \underbrace{\sum_{b=2}^{N-1} (N-b+1)}_{\text{等差数列部分}} - \underbrace{\sum_{b=2}^{N-1} \left\lfloor \frac{N}{b} \right\rfloor}_{\text{整除分块部分}} \end{align*}

  • \sum_{b=2}^{N-1} (N-b+1) 部分是一个等差数列求和,可以直接用公式计算。
  • -\sum_{b=2}^{N-1} \left\lfloor \frac{N}{b} \right\rfloor 部分则可以通过分块优化高效计算。

关键思路

等差数列部分

由于 b2N-1(N-b+1) 形成一个首项为 N-1,末项为 2,共 N-2 项的等差数列。可以直接用等差数列求和公式计算:

\sum_{b=2}^{N-1} (N-b+1) = \frac{(N-2) \times (N+1)}{2}

整除分块部分

分块的核心思想

观察到 \left\lfloor \frac{N}{b} \right\rfloorb 的某些连续区间内取值是相同的。我们可以按照 \left\lfloor \frac{N}{b} \right\rfloor 的值 kb \in [2, N-1] 进行分块。对于每一个 k,计算对应区间内 b 的长度,然后将区间长度与该 k 的贡献相乘,累加到答案中。

如何找到每个分块的区间

设当前分块的起点为 left,此时 \left\lfloor \frac{N}{left} \right\rfloor = k。我们希望找到下一个分块的起点 LL > left),使得 \left\lfloor \frac{N}{L} \right\rfloor < k,并且 L 尽可能小。
用数学式表示为:

L = \min \left\{\, x \mid x > left,\;\left\lfloor \frac{N}{x} \right\rfloor < k \,\right\}

进一步推导,\left\lfloor \frac{N}{L} \right\rfloor < k \implies N < k \times L \implies L > \frac{N}{k},所以 L 取最小的满足 L > \frac{N}{k} 的整数,即

L = \left\lfloor \frac{N}{k} \right\rfloor + 1

最终,为了让分块区间尾不超过 N-1(即下一个分块区间头不超过 N),实际取 L = \min\left(\left\lfloor \frac{N}{k} \right\rfloor + 1,\, N\right)

每个分块的贡献

b \in [left, L-1] 这个区间内,\left\lfloor \frac{N}{b} \right\rfloor 的值都等于 \left\lfloor \frac{N}{left} \right\rfloor,区间长度为 L - left,所以这一段的总贡献为 (L - left) \times \left\lfloor \frac{N}{left} \right\rfloor

循环推进

每次处理完一个分块后,将 left 更新为 L,继续处理下一个分块。这个过程一直进行,直到分块的起点 left 超过 N-1,即循环条件为 left < N

最终实现

Python 3 实现:

n = int(input())
mod = 998244353

ans = 0

# 计算等差数列和部分:(n-b+1) 从 b=2 到 b=n-1
# 即首项为 n-1,末项为 2,共 n-2 项
ans += (n - 2) * (n + 1) // 2

# 分块计算 n//b 的和
# 分块区间在 [2, n-1],注意边界处理
left = 2  # 当前分块区间的起点
while left < n:
    k = n // left  # 当前分块内 n//b 的值
    L = min(n // k + 1, n)  # 下一个分块区间的起点,当前分块区间的终点+1,不能超过 n
    ans -= (L - left) * k   # 区间长度*贡献
    left = L                # 移动到下一个分块的起点

print(ans % mod)

C++ 实现:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const ll mod = 998244353;

int main() {
    ll n;
    cin >> n;

    ll ans = 0;

    // 计算等差数列和部分:(n-b+1) 从 b=2 到 b=n-1
    // 首项为 n-1,末项为 2,共 n-2 项
    // ans += (n-2)*(n+1)//2
    ans = (((((n - 2) % mod) * ((n + 1) % mod)) % mod) * ((mod + 1) / 2)) % mod;

    // 分块计算 n//b 的和, 注意边界处理
    ll left = 2;
    while (left < n) {
        // 当前分块内 n//b 的值
        ll k = n / left;
        // 下一个分块区间的起点,当前分块区间的终点+1,不能超过 n
        ll L = min(n / k + 1, n);
        // 区间长度*贡献
        ans = (ans + mod - ((L - left) % mod) * (k % mod) % mod) % mod;
        // 移动到下一个分块的起点
        left = L;
    }

    cout << ans << endl;
    return 0;
}