POJ - 2480+GCD+欧拉函数+积性函数

前置技能;
(1)
gcd()函数是一个非完全积性函数,
i f g c d ( a , b ) = = 1 , t h e n g c d ( n ( a b ) ) = g c d ( n , a ) g c d ( n , b ) if gcd(a,b)==1,then gcd(n*(a*b))=gcd(n,a)*gcd(n,b)。
(2)
∑gcd(i, N)也是一个积性函数,记为 f ( N ) f(N) ,并且更一般地将N唯一分解。
k = 1 N g c d ( i , N ) = f ( N ) = i = 1 N f ( p i c i ) \sum_{k=1}^N gcd(i,N)=f(N)=\prod_{i=1}^N f(p_i^{c_i})
其中, N = i = 1 N p i c i N=\prod_{i=1}^N p_i^{c_i}
(3)
k = 1 N g c d ( i , N ) = d N d ϕ ( N / d ) \sum_{k=1}^N gcd(i,N)=\sum_{d|N} d*\phi(N/d)
(4)
下面求解 f ( p c ) f(p^c)
由(3)
k = 1 g c d ( i , p c ) = d p c d ϕ ( p c / d ) \sum_{k=1} gcd(i,p^c)=\sum_{d|p^c} d*\phi(p^c/d)
注意到p^c 的约数d仅仅可能为p^k
并且有 ϕ ( p k ) = p k p k 1 \phi(p^{k})=p^k-p^{k-1} .
化简得, d p c d ϕ ( p c / d ) = k = 0 c p k ϕ ( p c / p k ) = k = 0 c p k ϕ ( p c k ) = k = 0 c 1 p k ( p c k p c k 1 ) + p c = k = 0 c 1 ( p c p c 1 ) + p c = c ( p c p c 1 ) + p c \sum_{d|p^c} d*\phi(p^c/d)=\sum_{k=0}^c p^k*\phi(p^c/p^k)=\sum_{k=0}^c p^k*\phi(p^{c-k})=\sum_{k=0}^{c-1} p^k*(p^{c-k}-p^{c-k-1})+p^c=\sum_{k=0}^{c-1} (p^{c}-p^{c-1})+p^c=c*(p^c-p^{c-1})+p^c

于是得到了下面这条key代码。

ll f(int p,int r)
{
    return (r+1)*qpow(p, r)-r*qpow(p, r-1);
}
#include<stdio.h>
#include<iostream>
#include<cmath>
#include<math.h>
#include<string>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector>
#define ms0(a) memset(a,0,sizeof(a))
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;

const int maxn=1e6;
int n;
struct node{
    int p,c;
}a[100];
//欧拉筛法( O(n)  )
//p[]来存放已得到的素数,np为已得到的素数个数,p从 0 开始
int np=0,p[maxn],v[maxn+10];
int gg(int n){
    for(int i=2;i<=n;i++){
        if(!v[i]) p[++np]=i;//此时的i为某个质数
        for(int j=1;j<=np && i*p[j]<=n;j++){
            v[i*p[j]]=1; //用这个合数的最小质因子去筛掉这个合数
            if(i%p[j]==0) break;
        }
    }
    return np;
}

int cnt;
void fenjie(int n)
{
    cnt=0;
    for(int i=1;i<=np && n>=p[i];i++){
        if(n%p[i]==0){
            a[++cnt].p=p[i];
            int ci=0;
            while(n%p[i]==0){
                ci++;
                n/=p[i];
            }
            a[cnt].c=ci;
        }
    }
    if(n>1){
        a[++cnt].p=n;
        a[cnt].c=1;
    }
}

ll qpow(ll a,ll n){
    ll ans=1;
    while(n){
        if(n&1) ans=ans*a;
        a=a*a;
        n/=2;
    }
    return ans;
}

ll f(int p,int r)
{
    return (r+1)*qpow(p, r)-r*qpow(p, r-1);
}

int main(){
    gg(maxn);
    while (~scanf("%d",&n))
    {
        ms0(a);
        fenjie(n);
        ll ans=1;
        for(int i=1;i<=cnt;i++)
        {
            ans*=f(a[i].p,a[i].c);
        }
        printf("%lld\n",ans);
    }
    return 0;
}
发布了67 篇原创文章 · 获赞 0 · 访问量 1519

猜你喜欢

转载自blog.csdn.net/qq_44846324/article/details/104515209
今日推荐