题解: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)

算法及复杂度

  • 算法:整除分块,分 两段;同商区间合并计算
  • 时间复杂度:
  • 空间复杂度: