• ACM学习历程—SNNUOJ1132 余数之和(数论)


    Description

    F(n) = (n % 1) + (n % 2) + (n % 3) + ...... (n % n)。其中%表示Mod,也就是余数。
    例如F(6) = 6 % 1 + 6 % 2 + 6 % 3 + 6 % 4 + 6 % 5 + 6 % 6 = 0 + 0 + 0 + 2 + 1 + 0 = 3。
    给出n,计算F(n)。

    Input

    输入1个数N(2 <= N <= 10^12)。

    Output

    输出F(n)。

    Sample Input

    6

    Sample Output

    3
     
    这是51NOD上的一道题,由于提交不了,所以搞到我们学校的OJ提交了。
    这个题目n达10^12这么大,自然不可能走一遍。
    然后由于n%i = n-[n/i]*i
    所以sum(n%i) = sum(n-[n/i]*i) = n*n - sum([n/i]*i)。
    考虑到取整那部分,当i在连续的一段区间内可能值会不变。
    =>[n/i] = [n/j] => j = n/(n/i)这里的除法为取下整。
    于是便可以考虑分组运算了。
     
    当然可以将i和n/i两组再次合并,这样理论上能减少一倍的时间。
     
    由于数据很大,用了C++高精度。
     
    代码:
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #define LL long long
    
    using namespace std;
    
    const int UNIT = 10;
    struct Bignum
    {
        int val[30];
        int len;
    
        Bignum()
        {
            memset(val, 0, sizeof(val));
            len = 1;
        }
    
        Bignum operator=(const LL &a)
        {
            LL t, p = a;
            len = 0;
            while (p >= UNIT)
            {
                t = p - (p/UNIT)*UNIT;
                p = p / UNIT;
                val[len++] = t;
            }
            val[len++] = p;
            return *this;
        }
    
        Bignum operator+(const Bignum &a) const
        {
            Bignum x = a;
            int L;
            L = a.len > len ? a.len : len;
            for (int i = 0; i < L; ++i)
            {
                x.val[i] += val[i];
                if (x.val[i] >= UNIT)
                {
                    x.val[i+1]++;
                    x.val[i] -= UNIT;
                }
            }
            if (x.val[L] != 0)
                x.len = L+1;
            else
                x.len = L;
            return x;
        }
    
        Bignum operator-(const Bignum &a) const
        {
            bool flag;
            Bignum x1, x2;
            if (*this > a)
            {
                x1 = *this;
                x2 = a;
                flag = 0;
            }
            else
            {
                x1 = a;
                x2 = *this;
                flag = 1;
            }
            int j, L = x1.len;
            for (int i = 0; i < L; ++i)
            {
                if (x1.val[i] < x2.val[i])
                {
                    j = i+1;
                    while (x1.val[j] == 0)
                        j++;
                    x1.val[j--]--;
                    while (j > i)
                        x1.val[j--] += UNIT-1;
                    x1.val[i] += UNIT-x2.val[i];
                }
                else
                    x1.val[i] -= x2.val[i];
            }
            while (x1.val[x1.len-1] == 0 && x1.len > 1)
                x1.len--;
            if (flag)
                x1.val[x1.len-1] = -x1.val[x1.len-1];
            return x1;
        }
    
        Bignum operator*(const Bignum &a) const
        {
            Bignum x;
            int i, j, up;
            int x1, x2;
            for (i = 0; i < len; i++)
            {
                up = 0;
                for (j = 0; j < a.len; j++)
                {
                    x1 = val[i]*a.val[j] + x.val[i+j] + up;
                    if (x1 >= UNIT)
                    {
                        x2 = x1 - x1/UNIT*UNIT;
                        up = x1 / UNIT;
                        x.val[i+j] = x2;
                    }
                    else
                    {
                        up = 0;
                        x.val[i+j] = x1;
                    }
                }
                if (up != 0)
                    x.val[i+j] = up;
            }
            x.len = i + j;
            while (x.val[x.len-1] == 0 && x.len > 1)
                x.len--;
            return x;
        }
    
        Bignum operator/(const int &a) const
        {
            Bignum x;
            int down = 0;
            for (int i = len-1; i >= 0; --i)
            {
                x.val[i] = (val[i]+down*UNIT) / a;
                down = val[i] + down*UNIT - x.val[i]*a;
            }
            x.len = len;
            while (x.val[x.len-1] == 0 && x.len > 1)
                x.len--;
            return x;
        }
    
        LL operator%(const LL &a) const
        {
            LL x = 0;
            for (int i = len-1; i >= 0; --i)
                x = ((x*UNIT)%a+val[i]) % a;
            return x;
        }
    
        bool operator>(const Bignum &a) const
        {
            int now;
            if (len > a.len)
                return true;
            else if (len == a.len)
            {
                now = len - 1;
                while (val[now] == a.val[now] && now >= 0)
                    now--;
                if(now >= 0 && val[now] > a.val[now])
                    return true;
                else
                    return false;
            }
            else
                return false;
        }
    }ans, tmp, ttmp;
    
    LL n;
    
    void work()
    {
        ans = n;
        ans = ans*ans;
        LL j;
        for (LL i = 1; i <= n; i++)
        {
            j = n/(n/i);
            tmp = i+j;
            ttmp = j-i+1;
            tmp = tmp*ttmp;
            tmp = tmp/2;
            ttmp = n/i;
            tmp = tmp*ttmp;
            ans = ans-tmp;
            i = j;
        }
    }
    
    void output()
    {
        for (int i = ans.len-1; i >= 0; --i)
            printf("%d", ans.val[i]);
        printf("
    ");
    }
    
    int main()
    {
        //freopen("test.in", "r", stdin);
        while (scanf("%lld", &n) != EOF)
        {
            work();
            output();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Struts2
    Struts2
    学习python的第九天
    学习python的第八天--作业
    学习python的第七天--作业
    学习python第六天 --作业
    学习python的第六天---1(理论)
    学习python第五天
    学习python第四天
    学习python第三天
  • 原文地址:https://www.cnblogs.com/andyqsmart/p/4905813.html
Copyright © 2020-2023  润新知