约数求和

题目

给定两个数X,Y(0 \leq X \leq Y \leq 2\times10^9),求区间[X,Y]中每个元素的约数个数的和

分析

f[x]表示x的约数个数,sum[x]=\sum_{i=1}^{x}f[i],答案即为sum[Y]-sum[X-1]

现在问题变为如何快速的求sum[N]的值

考虑整体:1-N中以i为倍数的有\lfloor \frac{N}{i} \rfloor个,sum[N]=\sum_{i=1}^{N}i\times \lfloor \frac{N}{i} \rfloor,现在时间复杂度为O(N)还需要优化

又注意到\lfloor \frac{N}{i} \rfloor的值的严格非增的:如N=12,序列为12,6,4,3,2,2,1,1,1,1,1,1.可以考虑将\lfloor \frac{N}{i} \rfloor相同的值一起计算

即对于相同的\lfloor \frac{N}{i} \rfloor值求一个区间[l,r],可知更新时l=r+1,而r=N/(N/l)(表示序列中大于等于\lfloor \frac{N}{l} \rfloor的个数)

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;

using LL = long long;
LL X, Y;
LL solve(LL);

int main(){
  cin >> X >> Y;
  cout << solve(Y) - solve(X - 1) << endl;
  return 0;
}

LL solve(LL N){
  if(N <= 1) return N;
  LL i, j, res = 0;
  for(i = 1; i <= N; i = j + 1){
    j = N / (N / i);
    res += (N / i) * (i + j) * (j - i + 1) / 2;
  }
  return res;
}

猜你喜欢

转载自blog.csdn.net/Hardict/article/details/82726503