zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    SGU 176.Flow construction (有上下界的最大流)
    POJ 2391.Ombrophobic Bovines (最大流)
    poj 1087.A Plug for UNIX (最大流)
    poj 1273.PIG (最大流)
    POJ 2112.Optimal Milking (最大流)
    SGU 196.Matrix Multiplication
    SGU 195. New Year Bonus Grant
    关于multicycle path
    ppt做gif动图
    codeforces 598A Tricky Sum
  • 原文地址:https://www.cnblogs.com/andyqsmart/p/4905813.html
Copyright © 2011-2022 走看看