zoukankan      html  css  js  c++  java
  • AcWing 199. 余数之和

    (sum_{i = 1}^{n} k mod i = n * k - sum_{i = 1}^{n} lfloor k / i floor * i)

    显然,(lfloor k / i floor) 是最棘手的,我们要想办法简化计算。

    证明单调性

    • 观察 (lfloor k / i floor),显然随着 (i) 的增大,这个式子是越来越小的。

    • 又因为有向下取整符号,所以该式子取值只能是整数。

    若我们设函数 (f(x) = lfloor k / x floor)。则画在坐标轴中应该是从高到低一条条横线。

    上图是一条 (f(x) = lfloor 10 / x floor) 的图像。

    证明该式子最多只有 (2sqrt{k}) 个取值

    分段讨论:

    • (i <= sqrt{k}) 时,因为 (i)(1)(sqrt{k}) 的整数,所以最多只有 (sqrt{k}) 个不同的 (lfloor k / i floor) 值。
    • (i > sqrt{k}) 时,(lfloor k / i floor <= sqrt{k}),又因为式子取整了,所以式子只能取(1)(sqrt{k}) 的整数,故最多也只有 (sqrt{k}) 个不同的 (lfloor k / i floor) 值。

    综上所述,(lfloor k / i floor) 最多只有 (2sqrt{k}) 个取值


    有关 当 (i > sqrt{k}) 时,(lfloor k / i floor <= sqrt{k}) 的证明:

    由于下取整,所以 (lfloor k / i floor * i <= k)

    假设 $lfloor k / i floor > sqrt{k} $,有 (lfloor k / i floor * i > lfloor k / i floor * sqrt{k} > sqrt{k} ^ 2 = k)。②

    ① 与 ② 矛盾


    通过以上步骤,我们可以知道这个答案由连续 (2sqrt{k}) 段不同的取值组成,那么我们只需要确定每种取值是下界 (l) 和 上界 (r)。通过 (sum_{i = l}^{r} lfloor k / i floor * i = sum_{i = l}^{r} lfloor k / l floor * i = lfloor k / l floor * (sum_{i = l}^{r}i)) 即可求得每一段对答案的贡献。((sum_{i = l}^{r}i)) 可以用等差数列求和公式计算。

    已知下界求上界

    假设我们知道一段相同取值的下界是 (x),若能求出上界,我们问题便解决了。

    猜想若下界是 (x),上界是 (r = lfloor k / lfloor k / x floor floor)

    第一步、求证 (lfloor k / x floor = lfloor k / r floor)

    • 由定义式可知 (r * lfloor k / x floor + q = k) ③,其中 (0 <= q < lfloor k / x floor),所以 (lfloor k / r floor = lfloorfrac{r * lfloor k / x floor + q}{r} floor = lfloor k / x floor + lfloor frac{q}{r} floor >= lfloor k / x floor)

    • (r >= lfloor k / (k / x ) floor = x),所以 (lfloor k / x floor >= lfloor k / r floor)

    综上 (lfloor k / x floor = lfloor k / r floor)


    第二步、求证 (lfloor k / (r + 1) floor ot = lfloor k / x floor)

    假设 (lfloor k / (r + 1) floor = lfloor k / x floor)

    那么有 ((r + 1) * lfloor k / x floor + q' = k),其中 (0 <= q < r + 1)

    把式子变化一下:

    $r * lfloor k / x floor + lfloor k / x floor + q' = k $ ④

    ③④ 联立,有:

    (lfloor k / x floor + q' < lfloor k / x floor)

    因为 (q' >= 0),所以该式子矛盾,故假设不成立。


    通过这两步及之前的单调性,我们知道 (lfloor k / lfloor k / x floor floor) 一定是上界

    算法

    所以算法就很好设计了:

    • (l = 1),算出上界 (r)。计算这段的贡献
    • 使 (l = r + 1),即跳到下一段计算贡献。
    • 重复知道算完 ([1, n]) 里所有段。

    (Tips:)

    1. (lfloor k / l floor = 0) 的时候,显然这段以及后面(有单调性)已经没有贡献了,可以 (break)。(或者直接设右端点为 (n)
    2. 注意右端点和 (n) 取个 (min),因为 $ > n$ 没有贡献了。
    #include <cstdio>
    #include <iostream>
    using namespace std;
    typedef long long LL;
    int n, k, l, r;
    LL ans;
    int main() {
    	scanf("%d%d", &n, &k);
    	ans = (LL)n * k;
    	for (l = 1; l <= n; l = r + 1) {
    	    if(k / l == 0) break;
    		r = min(k / (k / l), n);
    		ans -= (LL)(k / l) * (l + r) * (r - l + 1) / 2;
    	}
    	printf("%lld
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    寒假Day37:设计模式(封装+继承+多态等)
    INF ClassInstall32 Section详解
    VS2008编译的程序运行提示“由于应用程序配置不正确,应用程序未能启动”
    INF Models Section
    INF DDInstall.Services Section
    INF ClassInstall32.Services Section详解
    INF DDInstall Section
    INF SourceDisksNames Section 和 SourceDisksFiles Section详解
    sys文件查看DbgPrint函数打印的信息
    IRP(I/O Request Package)详解
  • 原文地址:https://www.cnblogs.com/dmoransky/p/11972783.html
Copyright © 2011-2022 走看看