题目链接

题目大意:给定\(n,k\),求\(\sum_{i = 1}^{n}k \bmod i\)

整除分块


解析:我们考虑大力化柿子

\[\sum_{i = 1}^{n}k \bmod i \]

\[=\sum_{i = 1}^{n}k-i \times \lfloor \frac{k}{i} \rfloor \]

\[=nk-\sum_{i = 1}^{n}i \times\lfloor \frac{k}{i} \rfloor \]

然后我们发现右边\(\sum_{i = 1}^{n}i \times\lfloor \frac{k}{i} \rfloor\)这个东西不是很好求,跑去现学整除分块,我们发现\(\lfloor \frac{k}{i} \rfloor\)这个东西是可以分成很多块,每一块内的\(\lfloor \frac{k}{i} \rfloor\)是不变的,我们将其提出,就是一个等差数列求和了

对于一个左端点为\(l\),对于\(\lfloor \frac{k}{i} \rfloor\)分块的块,其右端点为\(r = \lfloor \frac{k}{\lfloor \frac{k}{l} \rfloor} \rfloor\),假如\(\lfloor \frac{k}{l} \rfloor = 0\)那么\(r = n\)(至于怎么证明这玩意儿我还真不会)

程序就很好写了,注意\(r\)不能超过\(n\)

代码:

#include <algorithm>
#include <cstdio>
using namespace std;
long long n,k,ans;
int main(){
	scanf("%lld %lld",&n,&k);
	ans = n * k;
	for(long long l = 1,r;l <= n;l = r + 1)
		r = (k / l == 0) ? n : min(n,k / (k / l)),ans -= (((l + r) * (r - l + 1)) >> 1) * (k / l);
	return printf("%lld\n",ans),0;
}

相关文章:

  • 2022-12-23
  • 2021-09-21
  • 2018-05-11
  • 2021-10-03
  • 2021-08-26
猜你喜欢
  • 2022-12-23
  • 2021-09-20
  • 2021-12-27
  • 2021-10-23
相关资源
相似解决方案