⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 euler函数前n项和.cpp

📁 //Euler 函数前n项和 /* phi(n) 为n的Euler原函数 if( (n/p) % i == 0 ) phi(n)=phi(n/p)*i else phi(n)=phi(n/p
💻 CPP
字号:
//Euler 函数前n项和
/*
phi(n) 为n的Euler原函数
if( (n/p) % i == 0 ) phi(n)=phi(n/p)*i;
else phi(n)=phi(n/p)*(i-1);

对于约数:divnum
如果i|pr[j] 那么 divnum[i*pr[j]]=divsum[i]/(e[i]+1)*(e[i]+2) //最小素因子次数加1
否则 divnum[i*pr[j]]=divnum[i]*divnum[pr[j]] //满足积性函数条件

对于素因子的幂次 e[i]
如果i|pr[j]  e[i*pr[j]]=e[i]+1; //最小素因子次数加1
否则 e[i*pr[j]]=1; //pr[j]为1次

对于本题:
1. 筛素数的时候首先会判断i是否是素数。
    根据定义,当 x 是素数时 phi[x] = x-1
    因此这里我们可以直接写上 phi[i] = i-1 ;
        
2. 接着我们会看prime[j]是否是i的约数
   如果是,那么根据上述推导,我们有:phi[ i * prime[j] ] = phi[i] * prime[j]
   否则
      phi[ i * prime[j] ] = phi[i] * (prime[j]-1)
     (其实这里prime[j]-1就是phi[prime[j]],利用了欧拉函数的积性)
     经过以上改良,在筛完素数后,我们就计算出了phi[]的所有值。
     我们求出phi[]的前缀和
*/
#include<stdio.h>
#define limit 1000001
__int64 prime[limit+1] = {0} ;
char ok[limit+1] = {0} ;
__int64 phi[limit+1] = {0} ;
__int64 s[limit+1] ;

void shax()
{
	__int64 i , j ;
	for(i = 2 ; i <= limit ; i++)
	{
		if(ok[i] == 0) 
		{
			prime[++prime[0]] = i ;
			phi[i] = i - 1 ;
		}
		for(j = 1 ; j < = prime[0] && prime[j]*i <= limit ; j++)
		{
			ok[prime[j]*i] = 1 ; 
			if(i%prime[j] == 0)
			{
				phi[i*prime[j]] = phi[i] * prime[j] ;  
				break ;
			}
			else
				phi[i*prime[j]] = phi[i] * (prime[j] - 1 ) ;
		}
	}
}
int main()
{
	__int64 i ;
	phi[1] = 0 ;
	shax() ;
	for(i = 1 ; i <= limit ; i++)
		s[i] = s[i-1] + phi[i] ;
	while(1 == scanf("%I64d" , &i))
	{
		if(i == 0) break ;
		printf("%I64d\n" , s[i]) ;
	}
	return 0 ;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -