POJ 2480 Longge's Problem

    技术2022-05-20  36

    求1~n中每个数与n的最大公约数的和

    我的方法,先因式分解n,然后dfs求出n的所有约数,与n的最大公约数一定是n的某个因数,我们只要知道对每个d|n,gcd(i,n)=d,1<=i<=n,有几个i满足,即1~n中与n的最大公约数为d的数字的个数就好了,而这个个数正好是PHI(n/d),PHI为欧拉函数

     

    网上看到别人一个利用积性函数解决的

    http://scturtle.is-programmer.com/posts/19388.html

    在数论中的积性函数:对于正整数n的一个函数 f(n),当中f(1)=1且当a,b互质,f(ab)=f(a)f(b),在数论上就称它为积性函数。若某函数f(n)符合f(1)=1,且就算a,b不互质,f(ab)=f(a)f(b),则称它为完全积性函数。

     

    欧拉函数,gcd(n,k)(当k固定时)都是积性函数

     

    且当i,j互素时,gcd(i*j,m)=gcd(i,m)*gcd(j,m),所以gcd(n,k)是积性函数

    同时,积性函数的和也是积性函数

     

    n=a1^k1*a2^k2*...*am^km,且ai^ki与aj^kj互素(i!=j)

    所以,F(n)=F(a1^k1,n)*F(a2^k2,n)*...*F(am^km,n)

    而F(a^k)=∑a^k*PHI(a^(k-i)) 0<=i<=k

     

    我的代码:

    #include<iostream> #include<cstdio> #include<memory.h> using namespace std; int factor[10000],e[10000],f[10000]; __int64 n,ans,cnt,f_num; void split(__int64 n) { __int64 i; cnt=0; for(i=2;i*i<=n;i++) { if(n%i==0) { factor[cnt]=i; e[cnt]=0; while(n%i==0) { e[cnt]++; n/=i; } cnt++; } } if(n>1) { factor[cnt]=n; e[cnt++]=1; } } __int64 eular(__int64 n) { __int64 res=1,i; for(i=2;i*i<=n;i++) { if(n%i==0) { res*=i-1; n/=i; while(n%i==0) { res*=i; n/=i; } } } if(n>1) { res*=n-1; } return res; } void dfs(int val,int d) { if(d==cnt) { f[f_num++]=val; return; } __int64 sum=1,i; for(i=1;i<=e[d];i++) { sum*=factor[d]; dfs(val*sum,d+1); } dfs(val,d+1); } int main() { int i,j; while(scanf("%I64d",&n)!=EOF) { ans=0; split(n); f_num=0; dfs(1,0); //cout<<f_num<<endl; for(i=0;i<f_num;i++) { ans+=f[i]*eular(n/f[i]); //cout<<f[i]<<" "<<ans<<endl; } cout<<ans<<endl; } return 0; }


    最新回复(0)