• BZOJ2226:LCMSum(欧拉函数)


    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.

    Sample Input

    3
    1
    2
    5

    Sample Output

    1
    4
    55

    HINT

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

    Solution

    $sum_{i=1}^{n}lcm(i,n)$
    $=sum_{i=1}^{n}frac{i imes n}{gcd(i,n)}$
    $=frac{1}{2}(sum_{i=1}^{n-1}frac{i imes n}{gcd(i,n)}+sum_{i=n-1}^{1}frac{i imes n}{gcd(i,n)})+n$
    因为$gcd(a,b)=gcd(a-b,b)$,所以上面的两个$sum$可以合起来。
    $=frac{1}{2}sum_{i=1}^{n-1}frac{n^2}{gcd(i,n)}+n$
    设$gcd(i,n)=d$,把式子改为枚举$d$,那么与$n$的$gcd$为$d$的数有$φ(frac{n}{d})$个。
    $=frac{1}{2}sum_{d|n}frac{n^2 imes φ(frac{n}{d})}{d}+n$
    设$d'=frac{n}{d}$,上下约分一下
    $=frac{1}{2}sum_{d'|n}d' imes φ(d')+n$
    预处理出$φ$数组,然后枚举每一个约数去计算它对它所有倍数的贡献,复杂度是调和级数的$O(nlogn)$。

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #define N (1000009)
     5 #define MAX (1000000)
     6 #define LL long long
     7 using namespace std;
     8 
     9 inline int read()
    10 {
    11     int x=0,w=1; char c=getchar();
    12     while (c<'0' || c>'9') {if (c=='-') w=-1; c=getchar();}
    13     while (c>='0' && c<='9') x=x*10+c-'0', c=getchar();
    14     return x*w;
    15 }
    16 
    17 LL T,n,cnt,phi[N],ans[N],vis[N],prime[N];
    18 
    19 void Preprocess()
    20 {
    21     phi[1]=1;
    22     for (int i=2; i<=MAX; ++i)
    23     {
    24         if (!vis[i]) prime[++cnt]=i, phi[i]=i-1;
    25         for (int j=1; j<=cnt && i*prime[j]<=MAX; ++j)
    26         {
    27             vis[i*prime[j]]=1;
    28             if (i%prime[j]) phi[i*prime[j]]=phi[i]*(prime[j]-1);
    29             else {phi[i*prime[j]]=phi[i]*prime[j]; break;}
    30         }
    31     }
    32     for (int i=1; i<=MAX; ++i)
    33         for (int j=i; j<=MAX; j+=i)
    34             ans[j]+=i*phi[i]/2;
    35     for (int i=1; i<=MAX; ++i) ans[i]=ans[i]*i+i;
    36 }
    37 
    38 int main()
    39 {
    40     Preprocess();
    41     T=read();
    42     while (T--) n=read(), printf("%lld
    ",ans[n]);
    43 }
  • 相关阅读:
    如何正确设置数据库连接池的大小
    spring生命周期
    Spring高级进阶:BeanFactoryPostProcessor
    Spring Bean的生命周期(非常详细)
    表达式求值相关算法
    golang 命令行参数解析 hflag
    golang 标准命令行解析库 flag
    docker consul 环境搭建
    docker etcd 环境搭建
    mysql 事务
  • 原文地址:https://www.cnblogs.com/refun/p/10371410.html
Copyright © 2020-2023  润新知