数论,数学

gcd and lcm

Code

int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int lcm(int a,int b){return a/gcd(a,b)*b;}

gcd的几条性质

[gcd(x^a-1,x^b-1)=x^{gcd(a,b)}-1 ]

证明:
(gcd(x^a-1,x^b-1))
(=gcd(x^b-1,x^a-x^b))
(=gcd(x^b-1,x^b(x^{a-b}-1)))
(=gcd(x^b-1,x^{a-b}-1))

[gcd(fib[i],fib[j])=fib[gcd(i,j)] ]

(fib[]) 为广义斐波那契数列)

证明:
(gcd(fib[i+j],fib[j]))
(=gcd(fib[j],fib[i+j]-fib[j]))
(=gcd(fib[j],fib[i-1]*fib[j]+fib[i]*fib[j+1]-fib[j]))
(=gcd(fib[j],fib[i]*fib[j+1]))
(=gcd(fib[j],fib[i]))

线性筛

int pr[maxn],tot;
bool check[maxn];
void init(int n){
    check[1]=1;
    for(int i=2;i<=n;i++){
        if(!check[i]){
            pr[++tot]=i;
        }
        for(int j=1;j<=tot&&i*pr[j]<=n;j++){
            check[i*pr[j]]=1;
            if(i%pr[j]==0)break;
        }
    }
}

理论上来讲 (n) 以内的质数个数大约在 (n/ln(n)) 个左右

欧拉定理

[a^{varphi(n)}≡1(\% n)(gcd(a,n)=1) ]

(S={x_1,x_2,...,x_{varphi(n)}}) 为所有与 (n) 互质且 (le n) 的数。
显然 (x_i≡x_j(i≠j)(\% n)) 不成立。
再设 (T={a*x_1,a*x_2,...,a*x_{varphi(n)}})
(ecause gcd(a,n)=1)
( herefore a*x_i≡a*x_j(i≠j)(\% n)) 不成立
( herefore S=T)
( herefore prod_{i=1}^{varphi(n)}a*x_i≡prod_{i=1}^{varphi(n)}x_i(\% n))
( herefore a^{varphi(n)}≡1(\% n))

扩展欧拉定理

[a^bequiv egin{cases} a^{bmodvarphi(p)},\,&gcd(a,\,p)=1\ a^b,&gcd(a,\,p) e1,\,b<varphi(p)\ a^{bmodvarphi(p)+varphi(p)},&gcd(a,\,p) e1,\,bgevarphi(p) end{cases} pmod p ]

费马小定理

(a^{p-1}≡1(\% p)(p ext{ is prime}))

Code

(O(n))(1-n) 的欧拉函数

void init(int n){
	phi[1]=1;	
	for(int i=2;i<=n;i++){
		if(!check[i]){
			pr[++tot]=i;
			phi[i]=i-1;
		}
		for(int j=1;j<=tot&&i*pr[j]<=n;j++){
			check[i*pr[j]]=1;
			if(i%pr[j]==0){
				phi[i*pr[j]]=phi[i]*pr[j];
				break;
			}
			else phi[i*pr[j]]=phi[i]*phi[pr[j]];
		}
	}
}

(O(sqrt{n}))(n) 的欧拉函数

int phi(int n){
    int x=n,ret=n;
    for(int i=2;i*i<=n&&x>1;i++){
        if(x%i==0){
            ret=ret/i*(i-1);
            while(x%i==0)x/=i;
        }
    }
    if(x>1)ret=ret/x*(x-1);
    return ret;
}

逆元

逆元的引入

在做组合数取模的时候,常常要求((a/b)\%p^{[1]}),然而不同于加减乘,除法取模没有((a/b)\%p=(a\%p/b\%p)\%p)的性质。因此,我们引入乘法逆元的概念。

(a* b≡1(\%p)),则设(b=inv(a)),称(b)(a)的逆元,满足((a*b)\%p=(a\%p*b\%p)\%p)。这样,除法转换为乘法,就可以了。

所有的有理数都有一个与其对应的逆元。因此,对于两个整数(A,B),要计算(frac{A}{B})(实数除法)时,(A)不一定要被(B)整除。

对于两个取模过的数,逆元是怎么输出商的?它实际上是在对给定的取模过的数(a,b),找最小的两个(A,B),满足(A=x* p+a,B=y* p+b,A\%B=0),并返回(A/B)

求逆元的几种常用方法

1. 扩展欧几里得

欧几里得定理

想必都知道$$gcd(a,b)=gcd(b,a%b)$$

解关于(x,y)的方程(ax+by=gcd(a,b))

首先,我们先解出方程的一个特解,再通过特解推出其余的通解即可。

如何求特解

我们来看下面两个方程:

[ax_1+by_1=gcd(a,b) ]

[bx_2+(a\%b)y_2=gcd(b,a\%b) ]

(ecause gcd(a,b)=gcd(b,a\%b),)

( herefore ax_1+by_1=bx_2+(a\%b)y_2)

(ecause a\%b=a-floor(a/b)* b^{[2]})

( herefore ax_1+by_1=ay_2+b(x_2-floor(a/b)* y_2))

由等式两边的系数关系得$$x_1=y_2$$$$y_1=x_2-floor(a/b)* y_2$$
于是形成了一种递归关系,可用递归解决。

递归终止状态

我们知道在计算最大公约数的过程中,(b)最终会等于(0),此时(a=gcd(A,B)),因此,这时方程化为(a* x=gcd(A,B)),解得(x=1,y=0)

如何求通解

求得一组特解之后,我们发现,对于方程(ax+by=gcd(a,b)),当(x)增加(b/gcd)(y)减少(a/gcd)时,等式仍成立。

证明

(ax)项增加(a* b/gcd)(by)项减少(a* b/gcd)

于是可求得所有通解。

如何求最小非负整数解

此处以(x)为例,(y)同理。我们让(x)一直减(B/gcd)直至求出最小解,即让(x\%(B/gcd))即可。

解关于(x,y)的方程(Ax+By=C)

我们发现,当(C)不能整除(gcd(A,B))时,方程就不能化为(ax+by=gcd(a,b))的形式,因此就无解。否则有无数解,将方程两边同时除以(frac{C}{gcd(A,B)})求解即可。

Code
typedef long long D;
D egcd(D a,D b,D &x,D &y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}
	D ans=egcd(b,a%b,x,y),tmp=x;
	x=y;
	y=tmp-a/b*y;
	return ans;
}
D cal(D a,D b,D c){
	D x,y,g=egcd(a,b,x,y);
	if(c%g!=0)return -1;
	b=abs(b/g);
	x=(x*(c/g)%b+b)%b;
	return x;
}

利用扩展欧几里得求乘法逆元

因为$$a* x≡1(%p)$$
所以$$a* x+b* y=1$$
此时,若(1\%gcd(a,b)≠1),即(gcd(a,b)≠1),则该方程无解。
否则,设特解为(x_0),最小非负整数解(x=x_0\%m)。当(m<0)时,由于计算机取模一个负数与数学上的意义不同,所以应把模数取绝对值。当(x_0<0)时,取模的结果是一个负数,所以把答案加上(m)即可。

复杂度为(log)级。

Code

typedef long long D;
D egcd(D a,D b,D &x,D &y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}
	D ans=egcd(b,a%b,x,y),tmp=x;
	x=y;
	y=tmp-a/b*y;
	return ans;
}
D cal(D a,D m){
	D x,y,g=egcd(a,m,x,y);
	if(g!=1)return -1;
	m=abs(m/g);
	x=(x%m+m)%m;
	return x;
}

2. 利用费马小定理

(p)为质数时(a^{p-1}≡1(\%p)) ,对(a* x≡1(\%p))(x=a^{p-2}\%p)

复杂度为(log)级。

Code

typedef long long D;
D qpow(D x,D y,D p){
	D ans=1;
	while(y){
		if(y&1)ans=ans*x%p;
		x=x*x%p;
		y>>=1;
	}
	return ans;
}
D cal(D a,D p){
	return qpow(a,p-2,p);
}

组合数取模(Lucas 定理)

由于题目中给的(p)一般都是质数,所以下面我们默认(p)为质数

1. 错误方法

由上面的结论,我们得出$$C(n,m)=frac{n!}{m!(n-m)!}=n!* inv(m!)* inv((n-m)!)$$
直接使用扩展欧几里得或费马小定理求逆元来实现除法取模。

此方法的错误之处在于,对(a* x≡1(\%p),a)有逆元的前提条件时(a,p)互质。当(a,p)不互质,即(a)(p)的倍数时,不存在逆元,也就无法计算。

比如计算(C(7,5)\%5),正确答案应该是(frac{7* 6}{1* 2}\%5=21\%5=1),但计算过程中出现了(5)的倍数,取模(5)之后就变为(0),因此最后答案输出了(0)

2. Lucas定理

lucas定理可避免上述情况。

递归式:

(lucas(n,m,p))(C(n,m)\%p) (p)为质数),则

[lucas(n,m,p)=C(n\%p,m\%p,p)* lucas(n/p,m/p,p) ]

此处的(C(n,m,p))可直接通过逆元计算。

复杂度为(log)级。

证明

Code

typedef long long D;
D fac[100001];
void preparefac(D n,D p){
	fac[0]=1;
	for(D i=1;i<=n;i++){
		fac[i]=i*fac[i-1]%p;
	}
}
D qpow(D x,D y,D p){
	D ans=1;
	while(y>0){
		if(y%2)ans=ans*x%p;
		x=x*x%p;
		y/=2;
	}
	return ans;
}
D cal(D x,D y){
	return qpow(x,y-2,y);
}
D Div(D x,D y,D p){
	return x*cal(y,p)%p;
}
D C_(D n,D m,D p){
	if(m>n)return 0;
	return Div(Div(fac[n],fac[m],p),fac[n-m],p);
}
D C(D n,D m,D p){
	if(!m)return 1;
	return C_(n%p,m%p,p)*C(n/p,m/p,p)%p;
}

线性递推求逆元

首先 (1^{-1}≡1(\%p))
(p=k* i+r)
(k* i+r≡0(\%p))
等式两边乘 (i^{-1}* r^{-1})
(k* r^{-1}+i^{-1}≡0(\%p))
( herefore i^{-1}≡-k* r^{-1}(\%p))
( herefore i^{-1}≡-floor(frac{p}{i})* (p\%i)^{-1}(\%p))

Code

inv[1]=1;
inv[i]=(p-p/i)*inv[p%i]%p;

阶乘逆元

(i) 的阶乘逆元等于 (i-1) 的阶乘逆元乘以 (i) 的逆元。

Code

facinv[i]=facinv[i-1]*inv[i]%p;

CRT

用于求解一元线性同余方程组 (xequiv a_ipmod{m_i})
过程:

  1. (b_i=prod_{j eq i}m_j)
  2. (c_iequiv b_i^{-1}pmod{m_i})
  3. (ans=sum_{i=1}^n a_ib_ic_ipmod{prod_i m_i})

证明

对于(iin[1,n])(ansequiv a_i+sum_{j eq i} a_jb_jc_jpmod{m_i}),由于(m_i|b_j(j eq i))( herefore ansequiv a_ipmod{m_i})

exCRT

对于多个方程的情况,考虑将方程两两合并。

对于两个方程的情况(xequiv a_1pmod{m_1},xequiv a_2pmod{m_2})

转换:(x=m_1s+a_1=m_2t+a_2 Rightarrow m_1s-m_2t=a_2-a_1),使用exgcd求解

(gcd(m_1,m_2) mid a_2-a_1)时无解

高端数论

积性函数

(f(xy)=f(x)f(y)(xperp y))

完全积性函数

(f(xy)=f(x)f(y))

欧拉函数

定义

(varphi(n)=sum_{i=1}^n [iperp n])

性质

[varphi(p)=p-1(p ext{ is prime}) ]

显然,除了它本身以外的数都和该质数互质。

[varphi(p^k)=p^k-p^{k-1}(p ext{ is prime}) ]

(p^k) 不互质的数就是 (p) 的倍数,有 (frac{p^k}{p}=p^{k-1}) 个。

[varphi(a*b)=varphi(a)*varphi(b)(gcd(a,b)=1) ]

(S_x={) 所有与 (x) 互质且 (le x) 的数 (}) 。显然 (|S_x|=varphi(x))
(ecause gcd(a,b)=1,)
( herefore S_{a*b})(S_a,S_b) 一一对应。
( herefore |S_{a*b}|=|S_a|*|S_b|,)(varphi(a*b)=varphi(a)*varphi(b))

[varphi(2*n)=varphi(n)(n\% 2=1) ]

(varphi(2)=1) ,易证。

[varphi(n)=varphi(frac{n}{p})*p(p|frac{n}{p}) ]

(varphi(frac{n}{p})=frac{n}{p}*prod (1-frac{1}{p_i}))
(varphi(n)=p*frac{n}{p}*prod (1-frac{1}{p_i})=p*varphi(frac{n}{p}))

[varphi(n)=varphi(frac{n}{p})*(p-1)(p ext{ is prime},p|n,gcd(p,frac{n}{p})=1) ]

(varphi(p)=p-1) ,易证。

[sum_{d|n}varphi(d)=n ]

(f(n)=sum_{d|n}varphi(d))
(gcd(x,y)=1) 时, (f(x)*f(y)=xprod_{p_i是x的质因子}(1-frac{1}{p_i})*yprod_{p_i是y的质因子}(1-frac{1}{p_i})=x*yprod_{p_i是x*y的质因子}(1-frac{1}{p_i})=f(x*y))
( herefore f(n)) 是积性函数。
(f(p^k)=sum_{i=0}^k varphi(p^i)=p^k)
于是我们把 (n) 分解质因数:
(n=prod p_i^{k_i})
(f(n)=prod f(p_i^{k_i})=prod p_i^{k_i}=n)

公式

(varphi(x)=xprod (1-frac{1}{p_i}))
(p_i)(x) 的第 (i) 个质因子, (x≥2)(varphi(1)=1)
根据唯一分解定理, (x=prod p_i^{k_i})
( herefore varphi(x)=prod varphi(p_i^{k_i})=prod (p_i^{k_i}-p_i^{k_i-1})=xprod (1-frac{1}{p_i}))

其他常用函数

(epsilon(n)=[n=1])

(id(n)=n)

(1(n)=1)

(sigma_k(n)=sum_{dmid n}d^k)

其中(omega(n))表示(n)的本质不同质因子个数,是一个积性函数。

狄利克雷卷积

((f*g)(n)=sum_{dmid n}f(d)g(frac{n}{d}))

例子

[epsilon=mu*1 ]

[sigma_0=1*1 ]

[sigma=id*1 ]

[varphi=mu*id ]

(varphi=mu*id)证明

(varphi*1=id Rightarrow varphi*1*mu=id*mu Rightarrow varphi*epsilon=mu*id)

莫比乌斯反演

(f(n)=sum_{dmid n}g(d)Rightarrow g(n)=sum_{dmid n}mu(d)f(frac{n}{d}))


注:
[1] 在本文中,(\%)表示取模运算,等价于( ext{mod})
[2] (floor(x))表示(lfloor x floor)
原文地址:https://www.cnblogs.com/BlogOfchc1234567890/p/9863156.html