整除分塊

一個有趣的問題

求一個

\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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章