SPOJ (BNUOJ) LCM Sum

LCM Sum


Time Limit: 5000 ms     Case Time Limit: 5000 ms     Memory Limit: 262144 KB
Submit: 4     Accepted: 0
This problem will be judged on SPOJ. Original ID: LCMSUM.

[Prev][Next]

Description


Given n, calculate the sum LCM(1,n) + LCM(2,n) + .. + LCM(n,n), where LCM(i,n) denotes the Least Common Multiple of the integers i and n.

Input


The first line contains T the number of test cases. Each of the next T lines contain an integer n.


Output


Output T lines, one for each test case, containing the required sum.

Example

Sample Input :
3
1
2
5

Sample Output :
1
4
55


Constraints

1 <= T <= 300000
1 <= n <= 1000000


Input


Output


Sample Input

Sample Output

Source

own problem used for Codechef Snackdown Onsite
卡时卡的好紧

//思路 欧拉函数
gcd(i,n)=k 求出所有的这样i的和 n*(phi[n/k]*(n/k)/2)*k
lcm(i,n)=i*n/k; 所以 所有这样的i sigma(lcm(i,n))=n*[n*(phi[n/k]*(n/k)/2)8k]/k
整理得 n*n*phi[n/k]/2/k 然后sqrt(n) 时间复杂度是 预处理欧拉函数时间+Qsqrt(N),这个超时、、、
然后再整理,(i|n) sigma(lcm(i,n))=n*(n/k)*phi[n/k]/2; 把n/k 看成a 则 =n*a*phi[a]/2
这样就可以预处理所有的 lcm(i,N) 1<=i<=N 值, 输出直接是O(1);
//
超时代码
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 1000001
int phi[N];
#define __int64 long long
void set()//求欧拉函数
{
    int i,j;
    for(i=2;i<N;i++)
      if(i%2)
        phi[i]=i;
      else
        phi[i]=i/2;
    for(i=3;i<N;i+=2)
     if(phi[i]==i)
       for(j=i;j<N;j+=i)
        phi[j]=phi[j]/i*(i-1);
}
int main()
{
    set();
    int T;
    int m;
    __int64 n;
    __int64 sum;
    scanf("%d",&T);
    int i;
    while(T--)
    {
        scanf("%lld",&n);
        if(n==1) { printf("1\n");continue; }
        m=sqrt((double)n);
        sum=n*n*phi[n]/2;
        for(i=2;i<=m;i++)
         if(n%i==0)
         {
             sum+=n*n*phi[n/i]/2/i;
             if(i*i<n)
             {
                 sum+=n*n*phi[i]/2/(n/i);
             }
         }
         sum+=n;
        printf("%lld\n",sum);

    }
    return 0;
}




AC 代码

#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <algorithm> using namespace std; #define N 1000001 #define __int64 long long __int64 phi[N]; __int64 ans[N]; void set() { __int64 i,j; for(i=2;i<N;i++) if(i%2) phi[i]=i; else phi[i]=i/2; for(i=3;i<N;i+=2) if(phi[i]==i) for(j=i;j<N;j+=i) phi[j]=phi[j]/i*(i-1); ans[1]=1; for(i=2;i<N;i++) ans[i]=i*phi[i]/2+1; __int64 k;//开始变量定义成int 计算过程中导致超过 int范围 for(i=2;i<=1000;i++) { ans[i*i]+=i*phi[i]/2; for(j=i*i+i,k=i+1;j<N;j+=i,k++) ans[j]+=i*phi[i]/2+k*phi[k]/2; } } int main() { set(); int T; int n; scanf("%d",&T); while(T--) { scanf("%d",&n); printf("%lld\n",ans[n]*n); } return 0; }
原文地址:https://www.cnblogs.com/372465774y/p/2740066.html