BZOJ 2226 [Spoj 5971] LCMSum | 数论拆式子

题目:

http://www.lydsy.com/JudgeOnline/problem.php?id=2226


题解:

题目要求的是Σn*i/gcd(i,n) i∈[1,n]

把n提出来变成Σi/gcd(i,n) i∈[1,n] 最后乘个n

设gcd(i,n)==d 我们枚举约数可以得到

∑(∑i/d*(gcd(i,n)==d)) (外面的Σ枚举d)

把i/d这个式子除以d可以得到

Σ( Σj*(gcd(j,n/d)==1) ) (外面Σ枚举d,j与n互质)

由于n/d与d等价

Σ( Σj*(gcd(j,d)==1) ) (外面Σ枚举d,j与n互质)

所以求小于等于i的所有与其互质的自然数之和

利用欧拉函数的性质有结论 : i*φ(i)/2

所以枚举i求解

#include<cstdio>
#define N 2000005
#define MaxN 1000000
typedef long long ll;
using namespace std;
ll phi[N],ans;
bool nonprime[N];
int prime[N],tot,T,n;
int main()
{
    phi[1]=1;
    for (int i=2;i<=MaxN;i++)
    {
    if (!nonprime[i])
        phi[i]=i-1,prime[++tot]=i;
    for (int j=1;j<=tot;j++)
    {
        if ((ll)prime[j]*i>MaxN) break;
        nonprime[i*prime[j]]=1;
        if (i%prime[j]==0)
        {
        phi[i*prime[j]]=phi[i]*prime[j];
        break;
        }
        phi[i*prime[j]]=phi[i]*(prime[j]-1);
    }
    }
    for (int i=2;i<=MaxN;i++)
    phi[i]=phi[i]*i/2;
    scanf("%d",&T);
    while (T--)
    {
    scanf("%d",&n);ans=0;
    for (int i=1;i*i<=n;i++)
        if (n%i==0)
        {
        ans+=phi[i];
        if (i*i<n)
            ans+=phi[n/i];
        }
    printf("%lld\n",ans*n);
    }
    return 0;
}

 

posted @ 2018-01-04 15:35  MSPqwq  阅读(156)  评论(0编辑  收藏  举报