数论
埃氏筛
思路:从小的素数开始,往后排查大数。
是其倍数的话就维护:1.标记非素数 2.因数数减去 phi[j]/i ;
原理:即使筛去2、3……,排列依旧是按照一定顺序,所以可以进行上述操作2。
const int maxn = 1e6 ;
void get_phi()
{
for(int i = 0 ; i <= maxn ; i++)
{
phi[i] = i ;
isprime[i] = 1 ;
}
isprime[0] = 0 ;
isprime[1] = 0 ;
phi[1] = 0 ;
for(int i = 2 ; i <= sqrt(maxn) ; i++)//找合数因子
{
if(isprime[i])
{
for(int j = i ; j <= maxn ; j += i)//维护之后的数 的素数
{
isprime[j] = 0 ;
phi[j] -= phi[j]/i ;
}
}
}
//for(int i = 1 ; i <= 20 ; i++) printf("phi[%d]=%d\n",i,phi[i]) ;
return ;
}
欧拉筛
思路:
/如果是质数 则筛后边
/特点:不重复筛
isprime 用于从前往后找素数因子;也可以记录是否素数,即vis[素数]=0
prime记录素数因子
void getprime(int x)//欧拉筛
{
memset(prime,0,sizeof(prime)) ;
memset(isprime,1,sizeof(isprime)) ;
isprime[1] = 0 ;
int cnt = 0 ;
for(int i = 2 ; i <= x ; i++)
{
if(isprime[i]) prime[++cnt] = i ;
for(int j = 1 ; j <= cnt ; j++)//j用于prime[j]
{
if(prime[j]*i > x) break ;
isprime[prime[j]*i] = 0 ;
if(i%prime[j] == 0) break ;
}
}
for(int i = 1 ; i <= cnt ; i++) printf("%d ",prime[i]) ;
printf("\n") ;
for(int i = 2 ; i <= x ; i++)
{
if(isprime[i]) printf("%d ",i) ;
}
printf("\n") ;
return ;
}