gcd , l c m \gcd,lcm gcd,lcm
简记
g
c
d
(
x
,
y
)
=
(
x
,
y
)
,
l
c
m
(
x
,
y
)
=
[
x
,
y
]
gcd(x,y)=(x,y),lcm(x,y)=[x,y]
gcd(x,y)=(x,y),lcm(x,y)=[x,y].
g
c
d
,
l
c
m
gcd,lcm
gcd,lcm可以看做指数取
m
i
n
,
m
a
x
min,max
min,max.
简单应用:
求
x
1
,
x
2
.
.
.
x
n
x_1,x_2...x_n
x1,x2...xn的
g
c
d
gcd
gcd.
设
w
=
max
x
i
w=\max x_i
w=maxxi.
则复杂度为
O
(
n
+
log
w
)
O(n+\log w)
O(n+logw).(因为每次做gcd的因子都非升,
w
w
w总共有
log
w
\log w
logw级别的因子数,所以得证).
欧拉定理
( a , m ) = 1 , a φ ( m ) ≡ 1 ( m o d m ) (a,m)=1,a^{\varphi (m)}\equiv 1 (\mod m) (a,m)=1,aφ(m)≡1(modm)
证明:对于 m m m的简化剩余系 x 1 , x 2 . . . . x φ ( m ) x_1,x_2....x_{\varphi(m)} x1,x2....xφ(m),每个数同乘 a a a,
这时得到的集合不变 ( a , b , c ⊥ m , a ≢ b → a c ≢ b c ( m o d m ) ) (a,b,c\bot m,a\not \equiv b\rightarrow ac\not \equiv bc(\mod m)) (a,b,c⊥m,a≡b→ac≡bc(modm)),所以得证.
拓展:
a
b
≡
a
m
i
n
(
b
,
b
m
o
d
φ
(
m
)
+
φ
(
m
)
)
,
d
=
(
a
,
m
)
>
1
a^b\equiv a^{min(b,b\mod \varphi(m)+\varphi(m))},d=(a,m)>1
ab≡amin(b,bmodφ(m)+φ(m)),d=(a,m)>1.
证明:对于
b
≤
φ
(
m
)
b\le \varphi(m)
b≤φ(m),显然取前面部分,保持不变.
此时,对于剩下部分,我们把 a a a的质因子按和 m m m是否互质分类.
显然如果互质的质因数的话, p φ ( m ) ≡ 1 ( m o d m ) p^\varphi(m)\equiv 1(\mod m) pφ(m)≡1(modm),所以删去若干 φ ( m ) \varphi(m) φ(m)的倍数无所谓.
引理:
∀ x a y b = k , a , b ≤ φ ( k ) \forall x^a y^b=k,a,b\le \varphi(k) ∀xayb=k,a,b≤φ(k).
先证明 k = p c , 满 足 c ≤ φ ( k ) k=p^c,满足c\le \varphi(k) k=pc,满足c≤φ(k).
考虑证明 p = 2 p=2 p=2, c = 1 , 2 , 3 c=1,2,3 c=1,2,3显然成立,然后归纳可证.
对于 p > 2 p>2 p>2等式右边增大,由 p = 2 p=2 p=2的情况推广即可.
对于 n = p c q d , 则 需 要 满 足 m a x ( c , d ) ≤ φ ( n ) n=p^cq^d,则需要满足max(c,d)\le \varphi(n) n=pcqd,则需要满足max(c,d)≤φ(n),这个可以由 c ≤ φ ( p c ) , d ≤ φ ( q d ) c\le\varphi(p^c),d\le \varphi(q^d) c≤φ(pc),d≤φ(qd)推得.
设
m
=
a
r
t
(
t
⊥
a
)
m=a^r t(t\bot a)
m=art(t⊥a),由欧拉定理得:
a
φ
(
t
)
≡
1
(
m
o
d
t
)
a^{\varphi(t)}\equiv 1(\mod t)
aφ(t)≡1(modt).
又因为
φ
(
t
)
∣
φ
(
m
)
\varphi(t)|\varphi(m)
φ(t)∣φ(m),所以
a
φ
(
m
)
≡
1
(
m
o
d
t
)
a^{\varphi(m)}\equiv 1(\mod t)
aφ(m)≡1(modt).
两边同时乘上
a
r
a^r
ar,则有
a
φ
(
m
)
+
r
≡
a
r
(
m
o
d
m
)
a^{\varphi(m)+r}\equiv a^r(\mod m)
aφ(m)+r≡ar(modm).
由引理可知
r
≤
φ
(
m
)
r\le \varphi(m)
r≤φ(m),又因为
c
>
φ
(
m
)
c>\varphi(m)
c>φ(m),所以
r
≤
c
,
a
c
=
a
c
−
r
+
r
=
a
c
−
r
+
φ
(
m
)
+
r
=
a
c
+
v
a
r
p
h
i
(
m
)
(
m
o
d
m
)
r\le c,a^c=a^{c-r+r}=a^{c-r+\varphi(m)+r}=a^{c+varphi(m)}(\mod m)
r≤c,ac=ac−r+r=ac−r+φ(m)+r=ac+varphi(m)(modm)
综上可得:
a
b
=
{
a
b
m
o
d
φ
(
m
)
(
a
⊥
m
)
a
b
(
(
a
,
m
)
>
1
,
b
≤
φ
(
m
)
a
b
m
o
d
φ
(
m
)
+
φ
(
m
)
o
t
h
e
r
w
i
s
e
a^b=\begin{cases} a^{b\mod \varphi(m)}(a\bot m) \\a^b((a,m)>1,b\le \varphi(m)\\a^{b\mod\varphi(m)+\varphi(m)}~~~~otherwise\end{cases}
ab=⎩⎪⎨⎪⎧abmodφ(m)(a⊥m)ab((a,m)>1,b≤φ(m)abmodφ(m)+φ(m) otherwise
a ( mod m ) a(\text{mod} ~~m) a(mod m)的阶
在 ( a , m ) = 1 (a,m)=1 (a,m)=1的情况下, a ( m o d m ) a(\mod m) a(modm)的阶可以简记为 o r d m ( a ) ord_m(a) ordm(a),它表示的是最小的x使得 a x ≡ 1 ( m o d m ) a^x\equiv 1(\mod m) ax≡1(modm).
显然
a
φ
(
m
)
≡
1
(
m
o
d
m
)
a^{\varphi(m)}\equiv 1(\mod m)
aφ(m)≡1(modm).
有性质:
o
r
d
m
(
a
)
∣
φ
(
m
)
ord_m(a)|\varphi(m)
ordm(a)∣φ(m),这个可以用反证法证明(设
φ
(
m
)
=
x
t
+
r
(
0
<
r
<
x
)
\varphi(m)=xt+r(0<r<x)
φ(m)=xt+r(0<r<x),然后可推出和最小性矛盾).
我们对
φ
(
m
)
\varphi(m)
φ(m)质因数分解,设
φ
(
m
)
=
∏
p
i
k
i
\varphi(m)=\prod p_i^{k_i}
φ(m)=∏piki.
我们记
o
=
x
o=x
o=x,初始时
o
=
φ
(
m
)
o=\varphi(m)
o=φ(m).
然后我们不断尝试除质因子即可.
原根
若 g 1 , g 2 . . . g φ ( m ) g^1,g^2...g^{\varphi(m)} g1,g2...gφ(m)在 m o d m \mod m modm下互不相等,那么我们称 g g g为模 m m m的原根.
性质:
- 有原根的 m = 1 , 2 , 4 , p a , 2 p a m=1,2,4,p^a,2p^a m=1,2,4,pa,2pa( p p p为奇素数).
-
m
m
m有
φ
(
φ
(
m
)
)
\varphi(\varphi(m))
φ(φ(m))个原根.
这个涉及群的一些奇怪的东西,目前还不会证明.
就证明一下比较简单的: p 有 φ ( p − 1 ) p有\varphi(p-1) p有φ(p−1)个原根吧:
先假设有一个原根 g g g,那么 g i ( i ⊥ p − 1 ) g^i(i\bot p-1) gi(i⊥p−1)也为原根.
证明显然,因为如果有 gcd ( i , p − 1 ) > 1 \gcd(i,p-1)>1 gcd(i,p−1)>1,那么在小于 φ ( p ) \varphi(p) φ(p)次内就会在 = 1 =1 =1,与定义矛盾.
所以原根总共有 φ ( p − 1 ) \varphi(p-1) φ(p−1)个.
原根的求法.(一般来说是对于奇素数 p p p而言求原根,然后使得一些运算转化为四则运算)
for i: [2,p)
for j in prime(p-1).
if i^((p-1)/j) = 1,不是原根.
当然由于原根较多可以采取随机的方法.
还有一种奇技淫巧是用 N T T NTT NTT卷积和暴力卷积进行对拍,拍上了就是原根.
裴蜀定理
(
a
,
b
)
=
d
,
则
存
在
a
x
+
b
y
=
d
(a,b)=d,则存在ax+by=d
(a,b)=d,则存在ax+by=d.
必要性比较显然,充分性可以利用欧几里得算法进行归纳证明.
卢卡斯定理:
( n m ) ≡ ( n % p n % p ) ( ⌊ n p ⌋ ⌊ m p ⌋ ) ( m o d p ) ) \boxed{\dbinom n m\equiv \dbinom{n\%p}{n\%p} \dbinom{\lfloor \dfrac n p\rfloor }{\lfloor \dfrac m p\rfloor }(\mod p))} (mn)≡(n%pn%p)(⌊pm⌋⌊pn⌋)(modp))
证明:二项式定理+费马小定理.
{ 1 + x p ≡ 1 + x ( 1 + x ) p ≡ 1 + x → ( 1 + x ) p ≡ 1 + x p ( m o d p ) → ( 1 + x ) n ≡ ( 1 + x ) ⌊ n p ⌋ p ( 1 + x p ) n % p ≡ ( 1 + x p ) ⌊ n p ⌋ ( 1 + x n % p ) ( m o d p ) \begin{cases} 1+x^p\equiv 1+x\\(1+x)^p \equiv 1+x\end{cases} \rightarrow (1+x)^p \equiv 1+x^p(\mod p)\rightarrow (1+x)^n\equiv(1+x)^{\lfloor \dfrac n p \rfloor p}(1 +x^p)^{n\%p}\equiv (1+x^p)^{\lfloor \dfrac n p \rfloor }(1+x^{n\%p})(\mod p) {1+xp≡1+x(1+x)p≡1+x→(1+x)p≡1+xp(modp)→(1+x)n≡(1+x)⌊pn⌋p(1+xp)n%p≡(1+xp)⌊pn⌋(1+xn%p)(modp).(费马小定理)
然后我们带入二项式定理,考究系数的关系.
为了方便,以后的下去整忽略不写.
∑ i = 0 n C n i x i ≡ ∑ i = 0 n / p C n / p i C n i x i p ∗ ∑ j = 0 n % p C n % p j x j ( m o d p ) \sum_{i=0}^n C_n^i x^i\equiv \sum_{i=0}^{ n/p} C_{n/p}^i C_n^i x^{ip} *\sum_{j=0}^{n\% p} C_{n\% p}^j x^j(\mod p) ∑i=0nCnixi≡∑i=0n/pCn/piCnixip∗∑j=0n%pCn%pjxj(modp)
∀ i ∈ [ 0 , n ] ∩ N , i = s p + t ( p , t ∈ N ) , C n i x i ≡ C n / p s x s p C n % p t x t \forall i\in [0,n]\cap \N,i=sp+t(p,t\in \N),C_n^ix^i\equiv C_{n/p}^s x^{sp}C_{n\%p}^tx^t ∀i∈[0,n]∩N,i=sp+t(p,t∈N),Cnixi≡Cn/psxspCn%ptxt
消去 x x x,则可得到卢卡斯定理.
实现:递归处理.复杂度: O ( log p n ) O(\log_p n) O(logpn).(不计预处理阶乘的时间)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll jc[N],jc_inv[N],ans;
ll power_mod(ll a,ll b,ll c)
{
ll ans=1%c;a%=c;
while(b>0)
{
if(b&1)ans=ans*a%c;
a=a*a%c;b=b>>1;
}
return ans;
}
int t,p,n,m;
void dfs(int a,int b)
{
if(!b)return;
dfs(a/p,b/p);
ans=ans*(jc[a%p]*jc_inv[a%p-b%p]*jc_inv[b%p]%p)%p;
}
int main()
{
scanf("%d",&t);
jc[0]=jc_inv[0]=1;
while(t--)
{
scanf("%d%d%d",&n,&m,&p);
ans=1;
for(int i=1;i<=p;i++)
{
jc[i]=jc[i-1]*i%p;
jc_inv[i]=power_mod(jc[i],p-2,p);
}
dfs(n+m,m);
printf("%lld\n",ans);
}
return 0;
}
拓展卢卡斯:
已知 n , m , p n,m,p n,m,p,求 ( n m ) m o d p \boxed{\dbinom n m \mod p} (mn)modp(其中 p p p不为质数)
推导:设 p = ∏ p i k i p=\prod p_i^{k_i} p=∏piki,则我们只要求解所有 ( n m ) m o d p i k i \dbinom n m \mod p_i^{k_i} (mn)modpiki,最后用中国剩余定理合并即可.
此时我们就求 n ! m ! ( n − m ) ! m o d p k \dfrac {n!}{m!(n-m)!}\mod p^k m!(n−m)!n!modpk(为了方便这里的p是质数,与上面的意义不同).
由于不一定有逆元,所以我们可以先把 p p p的倍数约去,即 n ! p x m ! p y ( n − m ) ! p z ∗ p x − y − z m o d p k \dfrac {\dfrac {n!}{p^x}}{\dfrac{m!}{p^y} \dfrac {(n-m)!} {p^z} }*p^{x-y-z}\mod p^k pym!pz(n−m)!pxn!∗px−y−zmodpk.
定义 F ( x ) F(x) F(x)表示 x ! x! x!除去 p p p的因子后 m o d p k \mod p^k modpk的结果.则有:
F ( x ) = p n / p F ( n / p ) ∏ i = 1 n / p k ∗ p k i ( i m o d p ≠ 0 ) ∏ i = n / p k ∗ p k + 1 n i ( i m o d p ≠ 0 ) F(x)=p^{n/p}F(n/p) \prod_{i=1}^{n/p^k*p^k} i(i\mod p\ne 0)\prod_{i=n/p^k*p^k+1}^n i(i\mod p\ne 0) F(x)=pn/pF(n/p)∏i=1n/pk∗pki(imodp=0)∏i=n/pk∗pk+1ni(imodp=0).
PS:前面部分表示含 p p p的因子的情况.
中间部分有周期性,我们可以减小枚举范围.
而且 p p p要消去,所以可以忽略.
所以 F ( x ) = F ( n / p ) ∗ ( ∏ i = 1 p k i ( i m o d p ≠ 0 ) ) n / p k ∗ ∏ i = 1 n − n / p k ∗ p k i ( i m o d p ≠ 0 ) F(x)=F(n/p)*(\prod_{i=1}^{p^k} i(i\mod p\ne 0))^{n/p^k}*\prod_{i=1}^{n-n/p^k*p^k} i(i\mod p\ne 0) F(x)=F(n/p)∗(∏i=1pki(imodp=0))n/pk∗∏i=1n−n/pk∗pki(imodp=0)
递归处理即可.递归层数 log p n \log_p n logpn,单层扫描 p k p^k pk.
总复杂度: O ( log p n p k ) O(\log_p^n p^k) O(logpnpk).
之后我们定义 G ( x ) G(x) G(x)表示 x x x中含有多少个 p p p个因子,复杂度: O ( log p n ) O(\log_p n) O(logpn).
单次求解 C n m m o d p i k i C_n^m \mod p_i^{k_i} Cnmmodpiki的复杂度: O ( p k log p n ) O(p^k \log_p^n) O(pklogpn).
合并复杂度: O ( log p k T ) , T O(\log p^k T),T O(logpkT),T为质因子个数.
总复杂度可以认为是: O ( p log p ) O(p\log p) O(plogp).
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=66;
typedef long long ll;
ll power(ll a,ll b,ll mod) {
ll c=1;
while(b&&c) {
if(b&1) c=c*a%mod;
b /= 2; a=a*a%mod;
}
return c;
}
void exgcd(ll a,ll b,ll &x,ll &y) {
if(!a) {x=0; y=1; return ;}
exgcd(b%a,a,y,x); x-=b/a*y;
}
ll inv(ll a,ll p) {
ll x,y; exgcd(a,p,x,y);
return (x%p+p)%p;
}
ll F(ll n,ll p,ll pk) {
if(!n) return 1;
ll s=1;
for(int i=1;i<pk;i++)
if(i%p) s=s*i%pk;
s=power(s,n/pk,pk);
for(int i=n%pk; i;i--)
if(i%p) s=s*i%pk;
return F(n/p,p,pk)*s%pk;
}
ll G(ll n,ll p) {
ll s=0;
while(n) s+=(n/=p);
return s;
}
ll C(ll n,ll m,ll p,ll pk) {
ll a=F(n,p,pk),b=inv(F(m,p,pk),pk),c=inv(F(n-m,p,pk),pk),d=power(p,G(n,p)-G(m,p)-G(n-m,p),pk);
return a*b%pk*c%pk*d%pk;
}
ll A[N],B[N];
ll lucas(ll n,ll m,ll p) {
int cnt=0;ll x=p;
for(int i=2;i*i<=x;i++) if(x%i==0) {
ll y=1;
while(x%i==0) y*=i,x/=i;
A[++cnt]=y; B[cnt]=C(n,m,i,y);
}
if(x>1) A[++cnt]=x,B[cnt]=C(n,m,x,x);
ll ans=0;
for(int i=1;i<=cnt;i++)
(ans += B[i]*(p/A[i])%p*inv(p/A[i],A[i])%p) %= p;
return ans;
}
int main() {
ll n,m,p; scanf("%lld%lld%lld",&n,&m,&p);
printf("%lld\n",lucas(n,m,p)); return 0;
}