P2261 [CQOI2007]余数求和 (数论)
题目链接:传送门
题目:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
题目背景 数学题,无背景 题目描述 给出正整数n和k,计算G(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值,其中k mod i表示k除以i的余数。例如G(10, 5)=5 mod 1 + 5 mod 2 + 5 mod 3 + 5 mod 4 + 5 mod 5 …… + 5 mod 10=0+1+2+1+0+5+5+5+5+5=29 输入输出格式 输入格式: 两个整数n k 输出格式: 答案 输入输出样例 输入样例#1: 10 5 输出样例#1: 29 说明 30%: n,k <= 1000 60%: n,k <= 10^6 100% n,k <= 10^9
思路:
有两点:(以下的除法都表示整数除法)
① k%n = k - k/n*n;
② 对于任意的正整数k,k/x的值的数量是√k级别的(1 ≤ x ≤ n)。
枚举k/x的值,则对于所有k/x的值相同的x,对应的k/x*x为一个公差为k/x的等差数列,用公式可以O(1)求出和。
总复杂度为O(√k)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define min(a, b) a<b?a:b ll N, k, ans; int main() { cin >> N >> k; ans = N*k; for (int x = 1, gx; x <= N; x = gx+1) { gx = k/x ? min(k/(k/x), N) : N; ans -= (k/x) * (x+gx) * (gx-x+1) / 2; } cout << ans << endl; return 0; }