gcd基本运算
g c d ( a , b ) = g c d ( a % b , b ) gcd\left( a,b \right) =gcd\left( a\%b,b \right) gcd(a,b)=gcd(a%b,b)
裴蜀定理
对于给定的正整数a,b,方程
a
∗
x
+
b
∗
y
=
c
a * x+b * y=c
a∗x+b∗y=c有解的充要条件为
c
c
c是
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b)的整数倍。根据逆元定义
a
a
∗
≡
1
(
m
o
d
b
)
a a^{*}\equiv 1(mod\ b)
aa∗≡1(mod b),则
a
a
∗
−
b
k
=
1
a a^{*}-b k=1
aa∗−bk=1
c=1时表明a,b互质是逆元存在的必要条件。同样可以证明:a,b互质是 a 在模 b 下存在逆元的充分条件。
扩展gcd
求解
g
c
d
(
a
,
b
)
=
a
x
+
b
y
gcd(a, b)=a x+b y
gcd(a,b)=ax+by中的
x
、
y
x、y
x、y
x
=
y
′
且
y
=
x
′
−
⌊
a
b
⌋
y
′
x=y^{\prime} \text { 且 } y=x^{\prime}-\left\lfloor\frac{a}{b}\right\rfloor y^{\prime}
x=y′ 且 y=x′−⌊ba⌋y′
int exgcd(int a, int b, int& x, int& y) {
if(a < b) return exgcd(b, a, y, x);
if(b == 0) {
x = 1; y = 0;
return a;
} else {
int x1;
int d = exgcd(b, a % b, x1, x);//算出x=y'
y = x1 - a / b * x;//算出y=x1-a/b*y'
return d;
}
}
欧拉函数
φ ( x ) = x ∏ i = 1 n ( 1 − 1 p i ) \varphi(x)=x \prod_{i=1}^{n}\left(1-\frac{1}{p_{i}}\right) φ(x)=xi=1∏n(1−pi1)其中 p i p_{i} pi为 x x x的质因子
① 当 m , n m,n m,n互质时,有 p h i ( m ∗ n ) = p h i ( m ) ∗ p h i ( n ) phi(m*n)= phi(m)*phi(n) phi(m∗n)=phi(m)∗phi(n);
② 若 i i%p==0 i,有 p h i ( i ∗ p ) = p ∗ p h i ( i ) phi(i*p) = p * phi(i) phi(i∗p)=p∗phi(i);
③ 对于互质的a和n,
a
φ
(
n
)
≡
1
(
m
o
d
n
)
a^{\varphi(n)} \equiv 1( \bmod\ n)
aφ(n)≡1(mod n)
(特别地,当n为质数时,
p
h
i
(
n
)
=
n
−
1
phi(n)=n-1
phi(n)=n−1,此时逆元为
a
n
−
2
a^{n-2}
an−2,即费马小定理)
④ 当n为奇数时, p h i ( 2 n ) = p h i ( n ) phi(2n)=phi(n) phi(2n)=phi(n)
⑤ 若x与p互质,则p-x也与p互质,因此小于p且与p互质的数之和为 p h i ( x ) ∗ x / 2 phi(x)*x/2 phi(x)∗x/2
⑥N>1,不大于N且和N互素的所有正整数的和是 1 / 2 ∗ N ∗ e u l a r ( N ) 1/2 *N *eular(N) 1/2∗N∗eular(N)。
⑦若(N%a == 0 && (N/a)%a==0) 则有: E ( N ) = E ( N / a ) ∗ a E(N)=E(N/a)*a E(N)=E(N/a)∗a;
⑧若(N%a==0 && (N/a)%a!=0) 则有: E ( N ) = E ( N / a ) ∗ ( a − 1 ) E(N)=E(N/a)*(a-1) E(N)=E(N/a)∗(a−1);
⑨
∑
d
∣
n
φ
(
d
)
=
n
\sum_{d \mid n} \varphi(d)=n
∑d∣nφ(d)=n
求单个
int pi(int x)
{
int ans=x;
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
}
求1–n
int primes[N], cnt; // primes[]存储所有素数
int euler[N]; // 存储每个数的欧拉函数
bool st[N]; // st[x]存储x是否被筛掉
void get_eulers(int n)
{
euler[1] = 1;
for (int i = 2; i <= n; i ++ )
{
if (!st[i])
{
primes[cnt ++ ] = i;
euler[i] = i - 1;
}
for (int j = 0; primes[j] <= n / i; j ++ )
{
int t = primes[j] * i;
st[t] = true;
if (i % primes[j] == 0)
{
euler[t] = euler[i] * primes[j];
break;
}
euler[t] = euler[i] * (primes[j] - 1);
}
}
}