思路:  ans[n]=  ans[n-1] + { (n,1),(n,2).....(n,n)}  现在任务 是 计算  { (n,1),(n,2).....(n,n)}(k=n的任意因子)  

  很明显  所有能取的k均为n的因子可以 sqrt(n) 内枚举。  若 p 为n的因子   那么  d(n,p) =p*p  *     {(n/p,1) ,(n/p,2) 。。。(n/p,n/p)}(后面这部分 k 取 1) 那么任务就转化成求   f(n)     f(n)表示 {(n,1),(n,2) ....(n,n)}当k等于1时候的值。 k等于1 相当于 枚举每个因子 p  。。求  sum*n          这边的sum表示与n/p互质的所有数之和。 sum=phi(n/p)*n/p ;

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<time.h>
#include<string>
#define REP(i,n) for(int i=0;i<n;++i)
#define REP1(i,a,b) for(int i=a;i<=b;++i)
#define REP2(i,a,b) for(int i=a;i>=b;--i)
#define MP make_pair
#define LL long long
#define X first
#define Y second
#define MAXN 500005
using namespace std;
LL MOD;
LL f[MAXN];
LL sum[MAXN];
LL phi[MAXN];
LL ans[MAXN];
void getphi()
{
    for(int i=1; i<MAXN; i++) phi[i]=i;
    for(int i=2; i<MAXN; i+=2) phi[i]>>=1;
    for(int i=3; i<MAXN; i+=2)
        if(phi[i]==i)
        {
            for(int j=i; j<MAXN; j+=i)
                phi[j]=phi[j]/i*(i-1);
        }
}
void init()
{
    MOD=1;
    REP(i,32)MOD*=2;
    getphi();
    for(int i=1;i<MAXN;++i)
        sum[i]=(phi[i]*i/2)%MOD;
    for(int i=1;i<MAXN;++i)
    {
        int j;
        f[i]=i;
        for(j=1;j*j<i;++j)
        {
            if(i%j==0)
            {
                f[i]=(f[i]+sum[j]*i)%MOD;
                f[i]=(f[i]+sum[i/j]*i)%MOD;
            }
        }
        if(j*j==i)
        {
            f[i]=(f[i]+sum[j]*i)%MOD;
        }
    }

    ans[1]=1;
    for(int i=2;i<MAXN;++i)
    {
        ans[i]=(ans[i-1]+f[i]);
        if(ans[i]>MOD)ans[i]-=MOD;
        int j;
        for(j=2;j*j<i;++j)
            if(i%j==0)
            {
                ans[i]=(ans[i]+((f[i/j]*j)%MOD)*j)%MOD;
                ans[i]=(ans[i]+((f[j]*(i/j))%MOD)*(i/j))%MOD;
            }
        if(j*j==i)
        {
            ans[i]=(ans[i]+((f[j]*j)%MOD)*j)%MOD;
        }
        ans[i]=(ans[i]+(LL)i*i)%MOD;
    }

}

int main() {
    init();

    int tt,ri=0;
    scanf("%d",&tt);
    while(tt--)
    {
        int n;
        scanf("%d",&n);
        printf("Case #%d: %I64d\n",++ri,ans[n]);
    }
    return 0;
}

 

posted on 2014-08-12 23:57  L_Ecry  阅读(290)  评论(0编辑  收藏  举报