51nod-1363: 最小公倍数之和

Posted never-mind

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod-1363: 最小公倍数之和相关的知识,希望对你有一定的参考价值。

【传送门:51nod-1363


简要题意:

  给出一个数n,求出1到n的数与n的最小公倍数的和

  多组数据


题解:

  理所当然推柿子

  原题相当于求$sum_{i=1}^{n}frac{i*n}{gcd(i,n)}$

  先枚举d=gcd(i,n),然后化简得到$$n*sum_{d|n}sum_{i=1}^{frac{n}{d}}i[gcd(i,frac{n}{d})==1]$$

  相当于求1到n-1中,与n互质的数和,设y<x,如果gcd(y,x)==1,那么gcd(x-y,x)==1,两式的贡献就是x了

  所以1到n-1中,与n互质的数和为$frac{phi(n)*n}{2}$,特殊的,如果n=1,则数和为1

  那么原式就等于$$n*sum_{d|n且d不为n}frac{frac{n}{d}*phi(frac{n}{d})}{2}+1$$

  再化简得到$$n+frac{n}{2}sum_{d|n且d>1}d*phi(d)$$

  这样,这个式子就变成$O(sqrt{n})$,但是多组数据仍会超时

  实际上我们将n质因数分解得到$n=prod_{i=1}^{x}p[i]^a[i]$

  因为p[i]两两互质,所以可以转化为$$n+prod_{i=1}^{x}sum_{j=0}^{a[i]}phi(p[i]^j)*p[i]^j$$

  根据欧拉函数的性质可以得到$$n+prod_{i=1}^{x}1+sum_{j=1}^{a[i]}(p[i]-1)*p[i]^{2j-1}$$

  再根据等比数列求和公式得到$$n+prod_{i=1}^{x}1+(p[i]-1)*frac{p[i]^{2*a[i]+1}-p[i]}{p[i]^2-1}$$

  $$n+prod_{i=1}^{x}1+frac{p[i]^{2*a[i]+1}-p[i]}{p[i]+1}$$

  然后线筛素数加速质因数分解就可以过了,记得最后处理1的情况


参考代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
LL Mod=1e9+7;
int prime[110000],m,v[110000];
void pre(int n)
{
    m=0;
    for(int i=2;i<=n;i++)
    {
        if(v[i]==0)
        {
            v[i]=i;
            prime[++m]=i;
        }
        for(int j=1;j<=m;j++)
        {
            if(prime[j]>n/i||prime[j]>v[i]) break;
            v[i*prime[j]]=prime[j];
        }
    }
}
LL p_mod(LL a,LL b)
{
    LL ans=1;
    while(b!=0)
    {
        if(b%2==1) ans=ans*a%Mod;
        a=a*a%Mod;b/=2;
    }
    return ans;
}
int main()
{
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    pre(100000);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        LL ans=1,d=n;
        for(int i=1;i<=m&&prime[i]<=n/prime[i];i++)
        {
            LL p=prime[i];
            if(n%p==0)
            {
                LL s=0;
                while(n%p==0) s++,n/=p;
                ans=ans*(1+p*((p_mod(p,2LL*s)-1+Mod)%Mod)%Mod*p_mod(p+1,Mod-2)%Mod)%Mod;
            }
        }
        ans=ans*(1+(LL)(n-1)*n%Mod)%Mod;
        ans=(ans-1+Mod)%Mod;
        printf("%lld
",(ans*d%Mod*p_mod(2LL,Mod-2)%Mod+d)%Mod);
    }
    return 0;
}

 

以上是关于51nod-1363: 最小公倍数之和的主要内容,如果未能解决你的问题,请参考以下文章

51nod1363-最小公倍数之和

51nod1363 最小公倍数之和

51nod 1096 距离之和最小 1108 距离之和最小 V2

51Nod 最大公约数之和V1,V2,V3;最小公倍数之和V1,V2,V3

51nod 1096 距离之和最小中位数

51nod1238 最小公倍数之和 V3