『约数之和 整除分块』
<更新提示>
<第一次更新>
<正文>
余数之和#
Description#
给出正整数n和k,计算j(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值
其中k mod i表示k除以i的余数。
例如j(5, 3)=3 mod 1 + 3 mod 2 + 3 mod 3 + 3 mod 4 + 3 mod 5=0+1+0+3+3=7
Input Format#
输入仅一行,包含两个整数n, k。
1<=n ,k<=10^9
Output Format#
输出仅一行,即j(n, k)。
Sample Input#
5 3
Sample Output#
7
解析#
注意到k%i=k−⌊ki⌋∗i,故$$\sum_{i=1}^n k%i=nk-\sum_{i=1}^n\lfloor \frac{k}{i} \rfloori$$
那么问题即求∑ni=1⌊ki⌋∗i。
引理:对于i∈[x,⌊k⌊kx⌋⌋],⌊ki⌋的值都相等,其证明如下:
设f(x)=⌊k⌊kx⌋⌋,显然有f(x)≥⌊k(kx)⌋=x,则可得⌊kf(x)⌋≤⌊kx⌋。
从另一方面考虑,则有⌊kf(x)⌋≥⌊kk⌊k/x⌋⌋=⌊kx⌋,则可得⌊kf(x)⌋=⌊kx⌋。
这样,每一次累加[x,⌊k⌊kx⌋⌋]所对应的值即可,可以证明这样的段不超过2√k个,我们称这种优化算法为整除分块。
Code:
#include<bits/stdc++.h>
using namespace std;
long long n,k,ans;
inline void input(void)
{
scanf("%lld%lld",&n,&k);
}
inline void solve(void)
{
ans=n*k;
for (long long l=1,r;l<=n;l=r+1)
{
r = k/l ? min(k/(k/l),n) : n;
ans -= (k/l)*(l+r)*(r-l+1)/2;
}
}
int main(void)
{
input();
solve();
printf("%lld\n",ans);
return 0;
}
<后记>
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 《HelloGitHub》第 108 期
· Windows桌面应用自动更新解决方案SharpUpdater5发布
· 我的家庭实验室服务器集群硬件清单
· C# 13 中的新增功能实操
· Supergateway:MCP服务器的远程调试与集成工具