zoukankan      html  css  js  c++  java
  • [BZOJ 1257] [CQOI2007] 余数之和sum 【数学】

    题目链接:BZOJ - 1257

    题目分析

    首先, a % b = a - (a/b) * b,那么答案就是 sigma(k % i) = n * k - sigma(k / i) * i     (1 <= i <= n)

    前面的 n * k 很容易算,那么后面的 sigma(k / i) * i,怎么办呢?

    我们可以分情况讨论,就有一个 O(sqrtk) 的做法。

    1)当 i < sqrtk 时,直接枚举算这一部分。

    2)当 i >= sqrtk 时, k / i <= sqrtk 。所以我们就可以枚举 k / i ,即枚举 [1, sqrtk] 的每一个数字。

       那么,对于我们枚举的每一个数字 x ,以它为 k / i 的 i 一定是连续的一段,它们的和可以用等差数列求和公式算出。

    于是就很明确了。

    代码

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <iostream>
     
    using namespace std;
     
    int n, k, SQRTK, L, R;
     
    typedef long long LL;
     
    LL Ans;
     
    int main()
    {
        scanf("%d%d", &n, &k);
        Ans = 0ll;
        if (n > k) Ans += (LL)(n - k) * k;
        n = n > k ? k : n;
        SQRTK = sqrt(k * 1.0);
        for (int i = 1; i <= SQRTK; i++) {
            if (i > n) break;
            Ans += (LL)k % i;
        }
        for (int i = 1; i <= SQRTK; i++) {
            L = (k / (i + 1)) + 1; L = L <= SQRTK ? SQRTK + 1: L;
            R = k / i; R = R > n ? n : R;
            if (R < L) continue;
            Ans += (LL)(R - L + 1) * ((k % L) + (k % R)) >> 1;
        }
        printf("%lld
    ", Ans);
        return 0;
    }
    

      

  • 相关阅读:
    Kendo
    过河
    数组分组(简单dp)
    Codeforces Round #604 (Div. 2)(A-E)
    HDU1253
    HDU1026
    linux常用命令(二) --目录操作
    linux常用命令(一)--ls
    hdu 1072
    Codeforces Round #597 (Div. 2)(A-D)
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4251985.html
Copyright © 2011-2022 走看看