title : 数论笔记(二)
date : 2021-8-5
tags : ACM,数论

拓展中国剩余定理
作用
解决模数不互质的问题
原理
合并和迭代思想
比
如
我
这
里
有
一
个
同
余
方
程
{
x
≡
a
1
m
o
d
m
1
x
≡
a
2
m
o
d
m
2
比如我这里有一个同余方程 \begin{cases} x\equiv a_1 \mod m_1\\ x\equiv a_2 \mod m_2\\ \end{cases}
比如我这里有一个同余方程{x≡a1modm1x≡a2modm2
那 么 m 1 x 1 + a 1 = m 2 x 2 + a 2 m 1 x 1 = ( a 2 − a 1 ) + m 2 x 2 m 1 x 1 = a 2 − a 1 m o d m 2 那么m_1x_1+a_1=m_2x_2+a_2\\ m_1x_1=(a_2-a_1)+m_2x_2\\ m_1x_1=a_2-a_1 \mod m_2 那么m1x1+a1=m2x2+a2m1x1=(a2−a1)+m2x2m1x1=a2−a1modm2
斐波那契数
递归方法定义 F ( 0 ) = 0 , F ( 1 ) = 1 , F ( n ) = F ( n − 1 ) + F ( n − 2 ) , n ≥ 2 F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2),n\ge2 F(0)=0,F(1)=1,F(n)=F(n−1)+F(n−2),n≥2
用待定系数法推导通项公式:(推导过程繁琐,利用等比数列,可自行查阅资料)
F ( n ) = 5 5 [ ( 1 + 5 2 ) n − ( 1 − 5 2 ) n ] F(n)=\frac{\sqrt5}{5}[(\frac{1+\sqrt5}{2})^n-(\frac{1-\sqrt5}{2})^n] F(n)=55[(21+5)n−(21−5)n]
更普遍的形式:
若
F
(
n
)
=
{
f
0
,
n
=
0
f
1
,
n
=
1
a
∗
F
(
n
−
1
)
+
b
∗
F
(
n
−
2
)
,
n
>
1
那
么
F
(
n
)
=
k
n
(
f
1
−
m
f
0
)
−
m
n
(
f
1
−
k
f
0
)
k
−
m
其
中
k
,
m
=
a
±
a
2
+
4
b
2
若F(n)=\begin{cases} f_0,n=0\\ f_1,n=1\\ a*F(n-1)+b*F(n-2),n>1 \end{cases}\\ 那么F(n)=\frac{k^n(f_1-mf_0)-m^n(f_1-kf_0)}{k-m}\\ 其中k,m=\frac{a\pm\sqrt{a^2+4b}}{2}
若F(n)=⎩⎪⎨⎪⎧f0,n=0f1,n=1a∗F(n−1)+b∗F(n−2),n>1那么F(n)=k−mkn(f1−mf0)−mn(f1−kf0)其中k,m=2a±a2+4b
斐波那契第一列通项公式(参考AHOI2004数字迷阵,第二行第一列的元素为前i-1行未出现的最小正整数,而A[i,2]=2A[i,1]-(i-1)
f [ i ] = t r u n c ( i ∗ t + i − 1 ) , 其 中 t = ( 1 + 5 ) / 2 f[i]=trunc(i*t+i-1),其中t=(1+\sqrt5)/2 f[i]=trunc(i∗t+i−1),其中t=(1+5)/2
卡特兰数
Catalan Number,是组合数学中一个经常出现在技术问题的数列。
前几项为:1,2,5,14,42,132,429,1430,4862,16796,58786,208012,742900…
求卡特兰数列第n项
1. 递 归 公 式 1 f ( n ) = ∑ i = 0 n − 1 f ( i ) × f ( n − i − 1 ) 2. 递 归 公 式 2 f ( n ) = f ( n − 1 ) ∗ ( 4 ∗ n − 2 ) n + 1 3. 组 合 公 式 1 f ( n ) = C 2 n n n + 1 4. 组 合 公 式 2 f ( n ) = C 2 n n − C 2 n n − 1 1.递归公式1\quad f(n)=\sum^{n-1}_{i=0}f(i)×f(n-i-1)\\ 2.递归公式2\quad f(n)=\frac{f(n-1)*(4*n-2)}{n+1}\\ 3.组合公式1\quad f(n)=\frac{C_{2n}^n}{n+1}\\ 4.组合公式2\quad f(n)=C_{2n}^n-C_{2n}^{n-1} 1.递归公式1f(n)=i=0∑n−1f(i)×f(n−i−1)2.递归公式2f(n)=n+1f(n−1)∗(4∗n−2)3.组合公式1f(n)=n+1C2nn4.组合公式2f(n)=C2nn−C2nn−1
常见的案例
左右括号、二叉树计算、欧拉多边形分割
斯特林数
第一类斯特林数
表示将n个不同元素构成m个圆排列的数目。
S ( n , m ) = S ( n − 1 , m − 1 ) + n S ( n − 1 , m ) S(n,m)=S(n-1,m-1)+nS(n-1,m) S(n,m)=S(n−1,m−1)+nS(n−1,m)
第二类斯特林数
表示将n个不同元素拆分成m个集合的方案数
S ( n , m ) = S ( n − 1 , m − 1 ) + m S ( n − 1 , m ) S(n,m)=S(n-1,m-1)+mS(n-1,m) S(n,m)=S(n−1,m−1)+mS(n−1,m)
卢卡斯定理
可以用来求 C ( n , m ) m o d p C(n,m)mod p C(n,m)modp的值,其中n和m是非负整数,p是素数。
一般用于m,n很大而p很小,或者n,m不大但大于p,这样用阶乘就解决不了。
结论1
L u c a s ( n , m , p ) = C ( n % p , m % p ) ∗ L u c a s ( n / p , m / p , p ) , L u c a s ( x , 0 , p ) = 1 ; 计 算 组 合 数 该 用 逆 元 : C ( a , b ) = ( a ! / ( a − b ) ! ) ∗ ( b ! ) ( p − 2 ) m o d p Lucas(n,m,p)=C(n\%p,m\%p)*Lucas(n/p,m/p,p),Lucas(x,0,p)=1;\\ 计算组合数该用逆元:C(a,b)=(a!/(a-b)!)*(b!)^{(p-2)} \mod p Lucas(n,m,p)=C(n%p,m%p)∗Lucas(n/p,m/p,p),Lucas(x,0,p)=1;计算组合数该用逆元:C(a,b)=(a!/(a−b)!)∗(b!)(p−2)modp
结论2
把n写成p进制a[n]a[n-1]a[n-2]…a[0],把m写成p进制b[n]b[n-1]b[n-2]…b[0],则C(n,m)与C(a[n],b[n])*C(a[n-1],b[n-1])*C(a[n-2],b[n-2])*…*C(a[0],b[0])模p同余
#include<bits/stdc++.h>
#define int long long
using namespace std;
int t,n,m,p;
int fpow(int a,int b){
int res=1;
while(b){
if(b&1) res=res*a%p;
a=a*a%p;
b>>=1;
}
return res;
}
int C(int a,int b){
if(a<b) return 0;
if(b>a-b) b=a-b;
int s1=1,s2=1;
for(int i=0;i<b;i++){
s1=s1*(a-i)%p; //a!/(a-b)!
s2=s2*(i+1)%p; //b!
}
return s1*fpow(s2,p-2)%p; //逆元
}
int Lucas(int a,int b){
if(b==0) return 1;
return C(a%p,b%p)*Lucas(a/p,b/p)%p;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>t;
while(t--){
cin>>n>>m>>p;
cout<<Lucas(n+m,n)%p<<endl;
}
return 0;
}
扩展卢卡斯定理
在 不 保 证 p 是 质 数 的 情 况 下 , 求 C n m m o d p 在不保证p是质数的情况下,求C_n^m\mod p 在不保证p是质数的情况下,求Cnmmodp
luoguP4720 【模板】扩展卢卡斯定理/exLucas
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, T b) { return b > a ? a = b, 1 : 0; }
ll n, m, p;
void Exgcd(ll a, ll b, ll &x, ll &y){ //扩展欧几里得
if (!b) x=1,y=0;
else Exgcd(b,a%b,y,x),y-=a/b*x;
}
inline ll fpm(ll x, ll power, ll Mod){ //快速幂
ll res = 1;
for (; power; power>>= 1,(x*=x)%=Mod)
if(power&1) (res*=x)%=Mod;
return res;
}
inline ll fac(ll n, ll pi, ll pk){ // 求阶乘
if(!n) return 1;
ll res=1;
for(int i=2;i<=pk;i++) if(i%pi) (res*=i)%=pk;
res=fpm(res,n/pk,pk);
for(int i=2;i<=n%pk;i++) if(i%pi) (res*=i)%=pk;
return res*fac(n/pi,pi,pk)%pk;
}
inline ll Inv(ll n, ll Mod){ //求逆元
ll x, y; Exgcd(n, Mod, x, y);
return (x % Mod + Mod) % Mod;
}
inline ll CRT(ll b, ll Mod){ //中国剩余定理合并答案
return b*Inv(p/Mod, Mod)%p*(p/Mod)%p;
}
inline ll factor(ll x, ll Mod) { //求x!中包含Mod因子的数量
return x?factor(x/Mod,Mod)+(x/Mod):0;
}
inline ll Comb(ll n,ll m,ll pi,ll pk){ //求组合数,pi为模数p的因子
ll k=factor(n,pi)-factor(m,pi)-factor(n-m,pi);
if (!fpm(pi,k,pk)) return 0;
return fac(n,pi,pk)*Inv(fac(m,pi,pk),pk)%pk*Inv(fac(n-m,pi,pk),pk)%pk*fpm(pi,k,pk)%pk;
}
inline ll ExLucas(ll n, ll m){ //扩展卢卡斯定理
ll res=0,tmp=p;
for(int i=2;i<=sqrt(p+.5);i++) if(!(tmp%i)){ //枚举模数因子
ll pk=1;
while(!(tmp%i)) pk*=i,tmp/=i;
(res+=CRT(Comb(n,m,i,pk),pk))%=p; //合并所有结果
}
if(tmp>1) (res+=CRT(Comb(n,m,tmp,tmp),tmp))%=p; //不要漏掉
return res;
}
signed main(){
cin>>n>>m>>p;
printf("%lld\n",ExLucas(n,m));
return 0;
}
约瑟夫问题
n个人,每次跳k。求最后一个被淘汰的人的位置
int Josephus(int n, int k) {
if (n == 1) return 0;
int res = 0;
if (n < k) {
For (i, 2, n)
res = (res + k) % i;
return res;
}
res = Josephus(n - n / k, k);
if (res < n % k)
res = res - n % k + n;
else
res = res - n % k + (res - n % k) / (k - 1);
return res;
}
参考资料
https://www.bilibili.com/video/BV1764y1R7kj
https://www.bilibili.com/video/BV1xb411x74F?
https://www.cnblogs.com/zjp-shadow/p/9267675.html#autoid-3-3-0

本文介绍了如何利用中国剩余定理解决模数不互质的同余方程组,涉及斐波那契数列的通项公式推导,以及卡特兰数、斯特林数和卢卡斯定理的计算技巧。此外,还探讨了约瑟夫问题的解决方案,以及一系列信息技术领域的数论工具在实际问题中的应用。
419

被折叠的 条评论
为什么被折叠?



