zoukankan      html  css  js  c++  java
  • 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;
    }

     

  • 相关阅读:
    Android java.lang.UnsupportedClassVersionError: com/android/dx/command/Main : Unsupported major.minor ver
    Android EditText光标位置(定位到最后)
    Android EditText获取光标位置并插入字符删除字符
    Android 仿微信小视频录制
    Android仿微信小视频录制功能
    Android消息机制之实现两个不同线程之间相互传递数据相互调用
    Android Data Binding 技术
    Android中解析XML
    Android 怎样把光标放在EditText中文本的末尾处?
    Hadoop HBase概念学习系列之RowKey设计(二十九)
  • 原文地址:https://www.cnblogs.com/Never-mind/p/9882196.html
Copyright © 2011-2022 走看看