Description
题目大意:
高效计算函数H(n)的值。
long long H( int n ) {
long long res = 0;
for( int i = 1; i <= n; i++ )
res = res + n / i;
return res;
}
思路
有个叫做数论分块的东西,可以计算考虑含有(leftlfloorfrac{n}{i}
ight
floor)的求和式子(n为常数)。
对于任意的i,我们要找到一个最大j,使得(leftlfloorfrac{n}{i}
ight
floor=leftlfloorfrac{n}{j}
ight
floor)。
事实上,(j=leftlfloorfrac{n}{leftlfloorfrac{n}{i}
ight
floor}
ight
floor)。
证明:
[leftlfloorfrac{n}{i}
ight
floor le frac{n}{i}
]
[leftlfloorfrac{n}{leftlfloorfrac{n}{i}
ight
floor}
ight
floor ge leftlfloorfrac{n}{frac{n}{i}}
ight
floor
]
[j=leftlfloorfrac{n}{leftlfloorfrac{n}{i}
ight
floor}
ight
floor ge i
]
用放缩易证(leftlfloorfrac{n}{i} ight floor=leftlfloorfrac{n}{j} ight floor)
所以这题就好办了,将n划分为若干区间[i,j]求和即可。
时间复杂度不清楚,代码跑了2000ms
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <cstring>
#include <string>
#include <stack>
#include <deque>
#include <cmath>
#include <iomanip>
#include <cctype>
#define endl '
'
#define IOS std::ios::sync_with_stdio(0);
#define pb push_back
#define mp make_pair
#define seteps(N) fixed << setprecision(N)
typedef long long ll;
using namespace std;
/*-----------------------------------------------------------------*/
#define INF 0x3f3f3f3f
const int N = 1e8 + 10;
const double eps = 1e-8;
int main() {
IOS;
int t;
cin >> t;
int cas = 0;
while(t--) {
ll n;
cin >> n;
ll cur = 1;
ll ans = 0;
while(cur <= n) {
ll tar = n / (n / cur);
ans += (tar - cur + 1) * (n / cur);
cur = tar + 1;
}
cout << "Case " << ++cas << ": " << ans << endl;
}
}