int phi[MAX] ; // 欧拉函数
bool Prime[MAX];// 判断是否是素数
int fac[MAX] ;// 按照顺序保存的素数
int prime[MAX] ; // 按照顺序保存的素数
int euler(int n ){ // 求 φ(n)
int cnt = 0 ;
int ans = n ;
for(int i = 2 ; i*i <=n ; i++) {
if(n%i==0) {
ans = ans/i *(i-1) ;
while(n%i == 0 ){
n/=i ;
}
}
}
if(n>1){
ans = ans/n *(n-1) ;
}
return ans ;
}
void phi_talbe(int n ){// 欧拉函数打表
for(int i = 2 ;i<=n ;i++ ) phi[i] = 0 ;
phi[1] = 1 ;
for(int i = 2 ; i<=n ; i++){
if(!phi[i]){
for(int j = i; j<=n; j+=i) {
if(!phi[j]){
phi[j] = j ;
}
phi[j] = phi[j]/i*(i-1) ;
}
}
}
return ;
}
唉式筛
const int M = 100000 ;
唉式筛
int Prime[M] ;
bool Is_Prime[M] ;
int sieve(int n )
{
int p = 0 ;
for(int i = 0 ;i<=n;i++)
{
Is_Prime[i] = true ;
}
Is_Prime[0] = Is_Prime[1] = false ;
for(int i = 2 ; i<=n ;i++)
{
if(Is_Prime[i])
{ // 如果是素数哦
Prime[++p] = i ;
for(int j = 2*i ; j<=n ;j+=i)
{
Is_Prime[j] = false ;
}
}
}
return p ;
}
线性筛
int prime[MAX] ;
int v[MAX] ;// 最小质因子
int primes(int n) {
int cnt = 0 ;
for(int i = 2 ; i<=n ; i++ ) {
if(!v[i]){ // i 是质数
v[i] = i ;
prime[++cnt] = i ;
}
for(int j = 1 ;j<=cnt ;j++ ){
// i 有比prime[j] 更小的质因子,或者超出n个范围
if(prime[j] > v[i] || prime[j]> n/i){
break ;
}
v[i*prime[j]] = prime[j] ;
}
}
return cnt // 返回n之内素数个数;
}
欧拉筛
int euler_n1(int n ){ // 欧拉筛素数
int cnt = 0 ;
memset(Prime,true,sizeof(Prime)) ;
Prime[0] = Prime[1] = false ;
for(int i = 2 ; i<n;i++ ){
if(Prime[i]){
prime[cnt++] = i ;
}
for(int j = 0 ; j<cnt &&fac[j]<=n/i ;j++ ){
Prime[i*prime[j]] = false;
if(i%prime[j]==0 ) {
break ;
}
}
}
return cnt ;
}
//欧拉线性筛:在线性时间内筛素数的同时求出所有数的欧拉函数
int get_phi(int n){
int cnt = 0 ;
phi[1] = 1 ;
for(int i = 2 ;i<=n ; i++ ) {
if(!Prime[i]){
prime[++cnt] = i ;
phi[i] = i-1 ;
}
for(int j = 1 ; j<=cnt ;j++ ) {
if(i*prime[j]>N) break ;
Prime[i*prime[j]] = 1 ;//确定i*prime[j]不是素数
if(i%prime[j] == 0 ){//判断prime[j] 是否为 i的约数
phi[i * prime[j]] = phi[i] * prime[j] ;
}
else{//prime[j] - 1 就是 phi[prime[j]],利用了欧拉函数的积性
phi[i*prime[j]] = phi[i] *(prime[j] -1) ;
}
}
}
return cnt ;
}