素数的判定
bool isprime(int n){
for(int i = 2; i <= sqrt(n); i++)
if(n % i == 0) return false;
return true;
}
素数筛
时间复杂度 O ( n ) O(n) O(n)
bool isprime[maxn];
int prime[maxn]; //保存的全是素数
int cnt; //素数的个数
void getprime(int n){
memset(isprime, true, sizeof isprime);
isprime[0] = isprime[1] = false;
cnt=0;
for(int i = 2; i <= n; i++){
if(isprime[i])
prime[cnt++] = i;
for(int j = 0; j < cnt && i * prime[j] <= n; j++){
isprime[i * prime[j]] = false;
if(i % prime[j] == 0) break;
}
}
}
素因数分解
N
=
p
1
c
1
p
2
c
2
…
p
m
c
m
N=p_1^{c_1}p_2^{c_2}…p_m^{c_m}
N=p1c1p2c2…pmcm
时间复杂度
O
(
n
)
O(\sqrt{n})
O(n)
int m;
int p[maxn],c[maxn];
void divide(int n){
m=0;
for(int i = 2; i <= sqrt(n); i++){
if(n % i == 0){
p[++m] = i,c[m] = 0;
while(n % i == 0) n /= i, c[m]++;
}
}
if(n > 1) //n是素数
p[++m] = n, c[m] = 1;
for(int i = 1; i <= m; i++)
cout<<p[i]<<'^'<<c[i]<<endl;
}
求 N 的正约数集合
时间复杂度 O ( n ) O(\sqrt{n}) O(n)
int factor[maxn];
void fac(int n){
int m=0;
for(int i = 1; i*i <= n; i++){
if(n % i == 0){
factor[++m] = i;
if (i != n/i) factor[++m] = n/i;
}
}
for(int i = 1; i <= m; i++)
cout<<factor[i]<<endl;
}
扩展欧几里得
B e z o u t Bezout Bezout 定理
对于任意整数 a , b a,b a,b,存在一对整数 x , y x,y x,y,满足 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)。
//返回a,b的最大公约数,并算出这样的x,y;
int exgcd(int a, int b, int &x, int &y){
if (b == 0) { x = 1, y = 0; return a; }
int d = exgcd(b, a % b, x, y);
int z = x; x = y; y = z - y * (a / b);
return d;
}
乘法逆元
若整数
b
,
m
b,m
b,m 互质,并且
b
∣
a
b|a
b∣a,则存在一个整数
x
x
x,使得
a
/
b
=
a
∗
x
(
m
o
d
m
)
a/b=a*x(mod \ m)
a/b=a∗x(mod m)。称
x
x
x 为
b
b
b 的模
m
m
m 乘法逆元,记为
b
−
1
(
m
o
d
m
)
b^{-1}(mod\ m)
b−1(mod m)。
b
∗
x
≡
1
(
m
o
d
m
)
b*x \equiv1(mod\ m)
b∗x≡1(mod m) 的
x
x
x 的解就是
b
b
b 的逆元,可以通过扩展欧几里得
算出。
求解过程:
由上式子
b
∗
x
≡
1
(
m
o
d
m
)
b*x \equiv1(mod\ m)
b∗x≡1(mod m) 得
b
∗
x
−
1
b*x-1
b∗x−1 是
m
m
m 的整数倍,我们假设就为
−
y
-y
−y 倍,即
b
∗
x
−
1
=
−
m
∗
y
b*x-1=-m*y
b∗x−1=−m∗y,所以就有
b
∗
x
+
m
∗
y
=
1
b*x+m*y=1
b∗x+m∗y=1。
乘法逆元递推
i
n
v
[
i
]
=
(
p
−
p
/
i
)
∗
i
n
v
[
p
%
i
]
%
p
(
p
!
=
2
,
且
为
素
数
)
inv[i]=(p-p/i)*inv[p \% i] \%p(p!=2,且为素数)
inv[i]=(p−p/i)∗inv[p%i]%p(p!=2,且为素数)
线性同余方程
给定整数
a
,
b
,
m
a,b,m
a,b,m,求一个整数
x
x
x 满足
a
∗
x
≡
b
(
m
o
d
m
)
a*x \equiv b(mod\ m)
a∗x≡b(mod m),或者给出无解,有解仅当
g
c
d
(
a
,
m
)
∣
b
gcd(a,m)|b
gcd(a,m)∣b。因为未知数
x
x
x 的指数为
1
1
1,所以我们称之为一次同余方程,也称线性同余方程。
a
∗
x
≡
b
(
m
o
d
m
)
a*x\equiv b(mod\ m)
a∗x≡b(mod m) 等价于
a
∗
x
−
b
a*x-b
a∗x−b 是
m
m
m 的倍数,不妨设为
−
y
-y
−y 倍。于是,该方程可以改写为
a
∗
x
+
m
∗
y
=
b
a*x+m*y=b
a∗x+m∗y=b,则该
x
x
x 就为方程的解。
根据
B
e
z
o
u
t
Bezout
Bezout 定理及其证明过程,线性同余方程有解仅当
g
c
d
(
a
,
m
)
∣
b
gcd(a,m)|b
gcd(a,m)∣b。
所以存在整数
k
k
k 使得
k
=
b
/
g
c
d
(
a
,
m
)
k=b/gcd(a,m)
k=b/gcd(a,m),即
g
c
d
(
a
,
m
)
=
b
/
k
gcd(a,m)=b/k
gcd(a,m)=b/k。所以有
a
∗
(
x
/
k
)
+
m
∗
(
y
/
k
)
=
g
c
d
(
a
,
m
)
a*(x/k)+m*(y/k)=gcd(a,m)
a∗(x/k)+m∗(y/k)=gcd(a,m),令
x
′
=
x
/
k
,
y
′
=
y
/
k
x^{'}=x/k,y^{'}=y/k
x′=x/k,y′=y/k,所以有
a
∗
x
′
+
m
∗
y
′
=
g
c
d
(
a
,
m
)
a*x^{'}+m*y^{'}=gcd(a,m)
a∗x′+m∗y′=gcd(a,m)。可以通过扩展欧几里得
算出
x
′
x^{'}
x′ 从而算出
x
x
x。