题解:BISHI41 【模板】整除分块
题目链接
题目描述
给定正整数 ,求表达式
的值。
解题思路
直接求和是 ,不可行。利用“整除分块”,当
处于一个区间内时,
取值相同。设
,则该
维持不变的最大右端点为
。于是把区间
一次性贡献:
,再令
继续。
该做法步数为不同商的个数,约为 。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
long long n;
if (!(cin >> n)) return 0;
long long ans = 0;
for (long long i = 1; i <= n; ) {
long long q = n / i;
long long r = n / q; // 最大 i 使得 floor(n/i)=q
ans += (r - i + 1) * q;
i = r + 1;
}
cout << ans << '\n';
return 0;
}
import java.io.*;
public class Main {
static class FastScanner {
private final InputStream in;
private final byte[] buffer = new byte[1 << 16];
private int ptr = 0, len = 0;
FastScanner(InputStream is) { this.in = is; }
private int read() throws IOException {
if (ptr >= len) { len = in.read(buffer); ptr = 0; if (len <= 0) return -1; }
return buffer[ptr++];
}
long nextLong() throws IOException {
int c; long sgn = 1, x = 0;
do { c = read(); } while (c <= 32);
if (c == '-') { sgn = -1; c = read(); }
while (c > 32) { x = x * 10 + (c - '0'); c = read(); }
return x * sgn;
}
}
public static void main(String[] args) throws Exception {
FastScanner fs = new FastScanner(System.in);
long n = fs.nextLong();
long ans = 0;
for (long i = 1; i <= n; ) {
long q = n / i;
long r = n / q;
ans += (r - i + 1) * q;
i = r + 1;
}
System.out.println(ans);
}
}
import sys
data = sys.stdin.buffer.read().split()
n = int(data[0])
ans = 0
i = 1
while i <= n:
q = n // i
r = n // q
ans += (r - i + 1) * q
i = r + 1
print(ans)
算法及复杂度
- 算法:整除分块,按相同商分组求和
- 时间复杂度:
- 空间复杂度: