Math
1. 积性函数
定义:若函数\(f(n)\)满足\(f(1) = 1\)&&\({\forall}{x,y}{\in}{N^{*}},gcd(x,y)=1\)都有\(f(xy)=f(x)*f(y)\)则\(f(n)\)为积性函数
若函数\(f(n)\)满足\(f(1)=1\)&&\({\forall}{x,y}{\in}{N^{*}}\)都有\(f(x,y)=f(x)*f(y)\)则\(f(n)\)为完全积性函数
性质:
若\(f(x),g(x)\)均为积性函数那么下面也为积性函数
\[ h(x) = f(x^p)\\ h(x) = f^P(x)\\ h(x) = f(x)*g(x)\\ h(x) = {\sum}\limits_{d\mid x}{f(d)g(\frac{x}{d})} \]例子:
欧拉函数,莫比乌斯函数
2.素数
暴力判断素数;
我们很明显可以发现:如果\(x\)是\(a\)的约数,那么\(\frac{a}{x}\)也是\(a\)的约数
inline bool init(int x)
{
if(x < 2) return 0;
for(int i = 1 ; i * i <= x ; i ++ )
{
if(x % i == 0) return false ;
}
return true ;
}
3.gcd,lcm
- STL :
int gcd = __gcd(x,y)
- 欧几里得
inline int gcd(int a , int b)
{
if(b == 0) return a ;
return (b , a % b) ;
}
inline int lcm(int a , int b)
{
1. return (a * b) / __gcd(a,b) ;
2. return (a * b) / gcd(a,b) ;
4.扩展欧几里得算法
\(求ax+by=gcd(a,b)\)的一组可行解
设
\[ax_1 + by_1 = gcd(a,b) \\ bx_2 +(a\ mod\ b)y_2 = gcd(a,b)\\ 显然gcd(a,b)=gcd(b,a\ mod\ b)\\ a\ mod\ b = a - \left \lfloor {\frac{a}{b}} \right \rfloor *b \\ \text{可以得到} \\ ax_1+by_1=bx_2+(a- \left \lfloor {\frac{a}{b}} \right \rfloor *b)y_2\\ ax_1+by_1=bx_2+ay_2-by_2 {\left \lfloor {\frac{a}{b}} \right \rfloor } \\ ax_1+by_1=b(x_2-y_2\left \lfloor {\frac{a}{b}} \right \rfloor)+ay_2\\ x_1 = y_2 , y_2 = x_2-y_2{\left \lfloor {\frac{a}{b}} \right \rfloor} \]inline void exgcd(int a , int b ,int &x , int &y)
{
if(b == 0)
{
x = 1 ;
y = 0 ;
return ;
}
exgcd(b , a % b , y , x) ;
y = y - (a / b) * x ;
}
5.筛法
-
埃氏筛:我们考虑一个数的倍数肯定也是素数就有了埃氏筛:
inline void init(int n) { int p = 0 ; for(int i = 0 ; i <= n ; i ++ ) is_prime[i] = true ; is_prime[0] = is_prime[1] = 0 ; for(int i = 2 ; i <= n ; i ++ ) { if(is_prime[i]) { prime[p++] = i ; if(i * i <= n) { for(int j = i * i ; j <= n ; j += i) { is_prime[j] = 0 ; } } } } return p ; }
2.线性筛(欧拉筛法)
inline void init(int n) { for(int i = 2 ; i <= n ; i ++ ) { if(use[i] == 0) prime[++cnt] = i ; for(int j = 1 ; j <= cnt && prime[j] * i <= n ; j ++ ) { use[i*prime[j]] = 1 ; if (i % prime[j] == 0) break ; } } }
3.筛法求欧拉函数
inline void init(int n) { in_prime[1] = 0 ; phi[1] = 1 ; for(int i = 2 ; i <= n ; i ++ ) { if(is_prime[i] == false) prime[++cnt] = i , phi[i] = i - 1 ; for(int j = 1 ; j <= cnt && prime[j] * i <= n ; j ++ ) { is_prime[i * prime[j]] = 0 ; if(i % prime[j] == 0) { phi[i * prime[j]] = phi[i] * prime[j] ; break ; } else phi[i*prime[j]] = phi[i] * phi[prime[j]] ; } } }
-
筛法求莫比乌斯函数
inline void init(int n) { mo[1] = 1 ; for(int i = 2 ; i <= n ; i ++ ) { if(use[i] == false) prime[++cnt] = i , mo[i] = -1 ; for(int j = 1 ; j <= cnt && prime[j] * i <= n ; i ++ ) { use[i*prime[j]] = true ; if(i % prime[j]) break ; mo[i*prime[j]] = - mo[i]; } } }