XTU 1203 A simple problem (2014 湖南湘潭邀请赛 A题)(数学)

来源:互联网 发布:完全数的算法 编辑:程序博客网 时间:2024/05/06 09:13

A simple problem

Accepted : 27 Submit : 296Time Limit : 15000 MS Memory Limit : 655360 KB

Problem Description

There is a simple problem. Given a number N. you are going to calculate N%1+N%2+N%3+...+N%N.

Input

First line contains an integer T, there are T(1≤T≤50) cases. For each case T. The length N(1≤N≤1012).

Output

Output case number first, then the answer.

Sample Input

15

Sample Output

Case 1: 4

Source

daizhenyang

    解题报告:
    一道不是特别难想的题,但是要注意很多细节。
    首先,求N模除1-N的和,N<=10^12,暴力是不可能的。我们可以找下规律。N%N=0,N%(N-1)=1,N%(N-2)=2,(N较大时)。
    可以发现,N 对 floor(N/2)+1到N的模除的结果依次减少1,模除的结果形成了等差数列。这是我们可以求的。
    同理可以求得(N/3, N/2)区间,(N/4, N/3)区间的模除和。
    这样岂不是要求到N/N?其实当(N/M)较小时,我们直接暴力求出(0, N/M)这段的模除和。
    算法基本就是这样。复杂度O(sqrt(n))。
    因为N很大,模除和超出了long long类型,需要使用大数。
    比赛的时候思路基本就是这样,我敲的时候缺犯了一个错误:
    后面的暴力和不会超过long long,而我用大数直接加上去……多一题就可以拿第二了,少了这题就是银首……
    贴个代码:
#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <iostream>#include <string>#include <set>#include <map>#include <queue>#include <vector>using namespace std;typedef long long LL;#define fff(i, n, m) for(int i=(n);i<=(m);i++)#define ff(i, n) for(int i=0;i<(n);i++)#define fout freopenvoid work();int main(){    #ifdef ACM    fout("in.txt", "r", stdin);    #endif    work();}/*==============================*/class Bignum{public:    int a[10];    int len;    Bignum()    {        memset(a, 0, sizeof(a));        len = 1;    }    Bignum(LL num)    {        memset(a, 0, sizeof(a));        len = 0;        while(num)        {            a[len++] = num%10000, num/=10000;        }        len = max(1, len);    }    Bignum(const Bignum & b)    {        memset(a, 0, sizeof(a));        len = b.len;        ff(i, len) a[i]=b.a[i];    }    int & operator[](int i)    {        return a[i];    }    Bignum operator+(const Bignum & b)    {        Bignum c;        c.len = max(len, b.len);        ff(i, c.len)        {            c[i] += a[i] + b.a[i];            if(c[i]>10000)                c[i+1]+=c[i]/10000, c[i]%=10000;        }        if(c[c.len]) c.len++;        return c;    }    Bignum operator*(const Bignum & b)    {        Bignum c;        c.len = len+b.len-1;        ff(i, len) ff(j, b.len)        {            c[i+j] += a[i]*b.a[j];            if(c[i+j]>10000)                c[i+j+1]+=c[i+j]/10000, c[i+j]%=10000;        }        if(c[c.len]) c.len++;        return c;    }    void print()    {        printf("%d", a[len-1]);        for(int i=len-2;i>=0;i--)            printf("%04d", a[i]);    }};void work(){    int T;    scanf("%d", &T);    fff(cas, 1, T)    {        LL n;        scanf("%I64d", &n);        LL sta = n, end = n;        Bignum ans;        LL t = 1;        LL m = sqrt(n+0.0);        m = (LL)(m * 7);    // 个人感觉相对较快        while(sta > m)        {            end = sta;            sta = n/(t+1);            LL r = n%end;            LL num = end - sta;            LL n1=num, n2=num-1;            if(n1%2==0) n1/=2; else n2/=2;            ans = ans + Bignum(r*num) + Bignum(n1)*Bignum(n2*t);            t++;        }        LL rr = 0;        while(sta)        {            rr+=n%sta;            sta--;        }        ans = ans+Bignum(rr);        printf("Case %d: ", cas);        ans.print();        puts("");    }}


0 0
原创粉丝点击