• BZOJ2226: [Spoj 5971] LCMSum


    BZOJ2226: [Spoj 5971] 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


    题解Here!
    题目要求:$$Ans=sum_{i=1}^nlcm(i,n)$$。
    乍一看,很像懵逼钨丝反演,但是只有一个$sum$。。。
    那就慢慢推式子。。。
    把那个$lcm$换成$gcd$:$$Ans=sum_{i=1}^nfrac{in}{gcd(i,n)}=nsum_{i=1}^nfrac{i}{gcd(i,n)}$$
    习惯性地枚举$gcd$:$$Ans=nsum_{d|n}sum_{i=1}^nfrac{i}{d}[gcd(i,n)==d]$$
    转变一下$i$:$$Ans=nsum_{d|n}sum_{i=1}^{frac{n}{d}}i imes [gcd(i,frac{n}{d})==1]$$
    然后因为$d|n$,所以$d==frac{n}{d}$,那么:$$Ans=nsum_{d|n}sum_{i=1}^di imes [gcd(i,d)==1]$$
    我们要求小于$d$且与$d$互素的所有自然数之和。
    根据欧拉函数的性质:小于$n$且与$n$互素的所有自然数之和为$frac{n imes varphi(n)}{2}$。
    原式可化为:$$Ans=nsum_{d|n}frac{d imes varphi(d)}{2}$$
    于是直接线性筛出$varphi(i)$,每个数暴力算到它的倍数里去,就可以预处理出答案了。
    复杂度是$O(nlog_2n+T)$。
    我也不知道为什么别人写的$O(n+Tsqrt{n})$的都能卡过,我只能写$O(nlog_2n+T)$的,我的常数真的这么大吗。。。
    附代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #define MAXN 1000010
    using namespace std;
    int n;
    int k=0,prime[MAXN],phi[MAXN];
    long long sum[MAXN],ans[MAXN];
    bool np[MAXN];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    void make(){
        int m=MAXN-10;
        phi[1]=1;
        for(int i=2;i<=m;i++){
            if(!np[i]){
                prime[++k]=i;
                phi[i]=i-1;
            }
            for(int j=1;j<=k&&prime[j]*i<=m;j++){
                np[prime[j]*i]=true;
                if(i%prime[j]==0){
                    phi[prime[j]*i]=phi[i]*prime[j];
                    break;
                }
                phi[prime[j]*i]=phi[i]*phi[prime[j]];
            }
        }
        sum[1]=1;
        for(int i=2;i<=m;i++)sum[i]=(long long)i*phi[i]/2;
        for(int i=1;i<=m;i++)
        for(int j=i;j<=m;j+=i)
        ans[j]+=sum[i];
        for(long long i=1;i<=m;i++)ans[i]*=i;
    }
    int main(){
        int t=read();
        make();
        while(t--){
            n=read();
            printf("%lld
    ",ans[n]);
        }
        return 0;
    }
    
  • 相关阅读:
    Grid++Report 报表开发工具
    docker(1):virtualbox 安装CoreOS系统,配置registry-mirror
    [Network]Introduction and Basic concepts
    Java进程堆外内存(off heap)大小
    可设置指定时间自己主动消失的 MessageBox实现
    《iOS Human Interface Guidelines》——Wallet
    什么是OpenStack
    Filters.h各种信号恢复滤波器头文件
    Android时间轴效果,直接使用在你的项目中
    浅析C++多重继承
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9478058.html
Copyright © 2020-2023  润新知