1 条题解
-
0
自动搬运
来自洛谷,原作者为

zzlzk
**搬运于
2025-08-24 21:37:33,当前版本为作者最后更新于2017-09-22 19:12:58,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
-
把用数学方式表示一下就是
-
那 $ans=\sum\limits_{i=x}^{y}f(i)=\sum\limits_{i=x}^{y}\sum\limits_{d|i}d$
-
那我们就可以直接枚举然后累加就可以了。
-
但这样的时间复杂度是,会
-
所以换一种思路,枚举约数
-
考虑中有几个数是 的倍数
-
假如中存在 的倍数,那这个数肯定可以表示为
-
的范围可以再简化一下,$1\leq k·d\leq n\Rightarrow 1 \leq k \leq \lfloor\frac{n}{d}\rfloor$
-
也就是说从 中把 的倍数单独拿出来,那就是
-
所以中 的倍数的个数就是
-
求出 的个数,再减去 的个数,也就是 的个数,这个是比较好想的,所以我就不详细说了。
-
这样就可以表示为
-
那$ans=\sum\limits_{i=1}^{y}(\lfloor\frac{y}{i}\rfloor*i)-\sum\limits_{i=1}^{x-1}(\lfloor\frac{x-1}{i}\rfloor*i)$
-
这种做法时间复杂度是,还是会
-
再看
-
只看,胡乱找个数列出来的值
-
以为例,列出来是 ,第 个数表示的值
-
发现这里面有些数是重复的,考虑能不能把这些重复的一次算出来
-
把那些相同的值用区间来表示,那只要求出左右端点来就好了
-
比较好求,观察上面的数列, 就是上一个加,初始
-
那 怎么求呢?
其实很简单 -
-
是那个数列的下标,所以 就是约数,那 就显然了,如果不知道为什么,那就再看一遍“中有几个数是 的倍数”。
-
和 都知道了, 那答案呢?
-
约数*约数的个数
-
约数
-
约数的个数,用等差数列求和公式表示一下就是
-
即
-
然后就愉快的AC啦!
比题解不知道短到那里去的代码#include<cstdio> using namespace std; typedef long long ll; ll sum(int n) { if(n<=1) return n; ll ans=0; for(ll l=1,r;l<=n;l=r+1) { r=n/(n/l); ans+=(n/l)*(l+r)*(r-l+1)/2; } return ans; } int main() { int x,y; scanf("%d%d",&x,&y); printf("%lld\n",sum(y)-sum(x-1)); return 0; } -
- 1
信息
- ID
- 1451
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者