码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-10-23 22:57:23      阅读:368      评论:0      收藏:0      [点我收藏+]

标签:

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)这里的除法为取下整。
于是便可以考虑分组运算了。
由于数据很大,用了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("\n");
}

int main()
{
    //freopen("test.in", "r", stdin);
    while (scanf("%lld", &n) != EOF)
    {
        work();
        output();
    }
    return 0;
}
View Code

 

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

标签:

原文地址:http://www.cnblogs.com/andyqsmart/p/4905813.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!