题解 | #余数求和#
余数求和
https://www.nowcoder.com/practice/5d18ffe2c6cd45ac8d8040be19c96f14
题解:BISHI42 余数求和
题目链接
题目描述
给定正整数 ,计算 
。
解题思路
将求和拆成两部分:当  时,有 
,贡献为 
;其余 
 用整除分块:
。令 
,在区间 
 上 
 不变,且 
,于是区间贡献为
。
整体复杂度 
。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    long long n, k;
    if (!(cin >> n >> k)) return 0;
    long long r = min(n, k);
    __int128 ans = ( (__int128)(n - r) ) * k;
    long long i = 1;
    while (i <= r) {
        long long q = k / i;
        long long R = min(r, k / q);
        long long cnt = R - i + 1;
        __int128 sum_i = (__int128)(i + R) * cnt / 2;
        ans += (__int128)cnt * k - (__int128)q * sum_i;
        i = R + 1;
    }
    unsigned long long out = (unsigned long long)ans;
    cout << out << '\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 k = fs.nextLong();
        long r = Math.min(n, k);
        // use BigInteger-like via long with care; values fit in 128-bit in C++, here we manage by splitting
        // We'll accumulate in long using careful ordering since bounds通常在1e12内;若更大,可改为 BigInteger
        // 仍保持模板清晰:用两个 long 累加不同项避免中间溢出
        long i = 1;
        // base
        java.math.BigInteger ans = java.math.BigInteger.valueOf(n - r).multiply(java.math.BigInteger.valueOf(k));
        while (i <= r) {
            long q = k / i;
            long R = Math.min(r, k / q);
            long cnt = R - i + 1;
            java.math.BigInteger sum_i = java.math.BigInteger.valueOf(i + R)
                    .multiply(java.math.BigInteger.valueOf(cnt))
                    .divide(java.math.BigInteger.valueOf(2));
            ans = ans.add(java.math.BigInteger.valueOf(cnt).multiply(java.math.BigInteger.valueOf(k))
                    .subtract(java.math.BigInteger.valueOf(q).multiply(sum_i)));
            i = R + 1;
        }
        System.out.println(ans.toString());
    }
}
import sys
data = sys.stdin.buffer.read().split()
n = int(data[0]); k = int(data[1])
r = min(n, k)
ans = (n - r) * k
i = 1
while i <= r:
    q = k // i
    R = min(r, k // q)
    cnt = R - i + 1
    sum_i = (i + R) * cnt // 2
    ans += cnt * k - q * sum_i
    i = R + 1
print(ans)
算法及复杂度
- 算法:整除分块,分 与 两段;同商区间合并计算 
- 时间复杂度:
- 空间复杂度:
 查看9道真题和解析
查看9道真题和解析