整除分块

一个有趣的问题

求一个

\sum_{i=1}^{N}\left \lfloor \frac{N}{i} \right \rfloor ,N\leq 10^{12}

1.\left \lfloor \frac{N}{i} \right \rfloor最多只有2\sqrt{N}种取值不同

2.设 \left \lfloor \frac{N}{i'} \right \rfloor\left \lfloor \frac{N}{i} \right \rfloor相等,则i'的最大值为 \left \lfloor \frac{N}{\left \lfloor \frac{N}{i} \right \rfloor} \right \rfloor

证明不证

所以 我们就可以设置两个指针L R, L初值赋值为1,每次令R=\left \lfloor \frac{N}{\left \lfloor \frac{N}{L} \right \rfloor} \right \rfloor,将(R-L+1)*\left \lfloor \frac{N}{L} \right \rfloor累加在答案中去,再令L=R+1

即可得到答案 因为\left \lfloor \frac{N}{i} \right \rfloor最多只有2\sqrt{N}种取值,所以时间复杂度为O(\sqrt{N}

代码如下:

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define db double
#define MAX 1000000
#define rep(i,j,k) for(int i=(int)(j);i<=(int)(k);i++) 
#define per(i,j,k) for(int i=(int)(j);i>=(int)(k);i--)
int main()
{
	//求n/i的和
	//  时间复杂度为根号N
	ll N = 100000000000;
	ll l, r;
	ll sum = 0;
	for (l = 1; l <= N; l = r + 1) {
		r = N / (N / l);
		sum += (r - l + 1)*(N / l);
	}
	cout << sum << endl;
	system("pause");
	return 0;
}

 

发布了44 篇原创文章 · 获赞 26 · 访问量 4357
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章