字典序全排列:按字典序对给定序列排序
① | ② | ③ | … | n ! / ( n 1 ! ∗ n 2 ! . . . n m ! ) n!/(n_1!*n_2!...n_m!) n!/(n1!∗n2!...nm!) |
---|---|---|---|---|
12344 | 12434 | 12443 | … | 44321 |
aabcc | aacbc | aaccb | … | ccbaa |
全排列数 =
n
!
/
(
n
1
!
∗
n
2
!
.
.
.
n
m
!
)
n!/(n_1!*n_2!...n_m!)
n!/(n1!∗n2!...nm!)
其中n为全排列的字母或数字总数,
n
1
,
n
2
,
.
.
.
,
n
m
n_1,n_2,...,n_m
n1,n2,...,nm为每个字母或数字出现的次数,除以它们阶层的积是为了除去因重复元素带来的重复排序。
c++库函数:
next_permutation:求字典序排序的下一个排列,若无下一个排列,则返回false
#include<algorithm>
bool next_permutation(iterator start, iterator end);
相应地有prev_permutation:求字典序排序的上一个排列,若无上一个排列,则返回false
#include<iostream>
#include<algorithm>
int q[3] = {1, 2, 3};
while(next_permutation(q, q+3))
{
for(int i = 0;i <3 ;i++)
cout << q[i] << ' ';
cout << endl;
}
扩展问题一:求一个序列的不同的排列数量
res =
n
!
/
(
n
1
!
∗
n
2
!
.
.
.
n
m
!
)
n!/(n_1!*n_2!...n_m!)
n!/(n1!∗n2!...nm!)
由于
n
!
n!
n!一般都很大,大多数题目要求对res%MOD
乘法逆元:若整数 b,m 互质,并且对于任意的整数 a,如果满足 b ∣ a b|a b∣a,则存在一个整数 x,使得 a b ≡ a ∗ x ( m o d m ) \frac{a}{b}≡a*x(mod\ m) ba≡a∗x(mod m),则称 x 为 b 的模 m 乘法逆元,记为 b − 1 ( m o d m ) b^{−1}(mod\ m) b−1(mod m)。
b 存在乘法逆元的充要条件是 b 与模数 m 互质。当模数 m 为质数时, b m − 2 b^{m−2} bm−2 即为 b 的乘法逆元。
费马定理:如果m是一个质数,且a不是m的倍数,则 a m − 1 ≡ 1 ( m o d m ) a^{m-1}\equiv1 (mod\ m) am−1≡1(mod m)
a
b
≡
a
∗
b
−
1
(
m
o
d
m
)
\frac{a}{b} \equiv a*b^{-1}(mod\ m)
ba≡a∗b−1(mod m)
a
≡
a
∗
b
−
1
∗
b
(
m
o
d
m
)
a \equiv a * b^{-1}*b(mod\ m)
a≡a∗b−1∗b(mod m)
b
−
1
∗
b
≡
1
(
m
o
d
m
)
b^{-1}*b\equiv 1(mod\ m)
b−1∗b≡1(mod m)
如果m为质数,且b不是m的倍数,则逆元存在
由费马定理知,如果m为质数,且b不是m的倍数,则
b
m
−
1
≡
1
(
m
o
d
m
)
b^{m-1} \equiv1(mod\ m)
bm−1≡1(mod m)
b
m
−
2
∗
b
≡
1
(
m
o
d
m
)
b^{m-2}*b \equiv 1(mod\ m)
bm−2∗b≡1(mod m)
b
−
1
≡
b
m
−
2
(
m
o
d
m
)
b^{-1} \equiv b^{m-2}(mod\ m)
b−1≡bm−2(mod m)