NEUOJ1403(数学~)

题目内容是求[n/1]+[n/2]+[n/3]+..+[n/3]。

累计当前已经处理过的分母,假设为pre,而且当前这个结果为i,那么i这个结果出现的次数是i*(n-pre-[n/(i+1)])。这样枚举到sqrt(n)以后结果出现的次数变得很少并且相隔很大,所以到此换一种枚举方法也就是从1开始枚举下标,一直到sqrt(n),边界处理稍微恶心一点。

#include <bits/stdc++.h>
using namespace std;

long long n;

long long solve () {
    long long pre = 0, ans = 0;
    long long Max = sqrt (n), cur, out;
    for (long long i = 1; i <= Max; i++) {
        cur = n-pre-(long long)(n/(i+1));
        pre += cur;
        ans += cur*i;
        if (i == Max) {
            out = i;
            break;
        }
    }
    for (long long i = 1; ; i++) {
        if ((long long)(n/i) == out)
            break;
        ans += (long long) (n/i);
    }
    return ans;
}

int main () {
    int t, kase = 0;
    scanf ("%d", &t);
    while (t--) {
        scanf ("%lld", &n);
        printf ("Case%d: %lld\n", ++kase, solve ());
    }
    return 0;
}
这本身是很水的题目。

不过有个很有趣的结论,发现f(n) = f(n-1) + g(n),f(n)是本题的结果,g(n)刚好是n的所有因数的个数。因此这道题也就是求1~n所有数的因数的个数和。


你可能感兴趣的:(NEUOJ1403(数学~))