【数论 】

五、数论

快速幂

ll quickpow(ll a,ll n,ll p){
    ll res = 1;
    while(n){
        if(n&1) res = res*a%p;
        a = a*a%p;
        n >> 1;
    }
    return res;
}

矩阵快速幂

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
struct maxtrix{
	ll c[101][101];
	maxtrix(){memset(c,0,sizeof c);}
}A,res;
ll n,k;
maxtrix operator*(maxtrix &x,maxtrix &y){
	maxtrix t;
	for(int i = 1 ; i <= n ; i++)
		for(int j = 1 ; j <= n ; j++)
			for(int k = 1 ; k <= n ; k++)
				t.c[i][j] = (t.c[i][j]+x.c[i][k]*y.c[k][j])%mod;
	return t;
}
void quickpow(ll k){
	for(int i = 1 ; i <= n ; i ++) res.c[i][i] = 1;
	while(k){
		if(k&1) res = res*A;
		A = A*A;
		k >>= 1;
	}
}
int main()
{
	cin >> n >> k;
	for(int i = 1 ; i <= n ; i ++)
		for(int j = 1 ; j <= n ; j ++)
			cin >> A.c[i][j];
	quickpow(k);
	for(int i = 1 ; i <= n ; i ++)
	{
		for(int j = 1 ; j <= n ; j ++)
			cout << res.c[i][j] << " ";	
		cout << endl;
	}
		
	
	return 0;
}

矩阵快速幂加速递推

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
struct maxtrix{
	ll c[3][3];
	maxtrix(){memset(c,0,sizeof c);}
}A,F;
maxtrix operator*(maxtrix &x,maxtrix &y){
	maxtrix t;
	for(int i = 1 ; i <= 2 ; i++)
		for(int j = 1 ; j <= 2 ; j++)
			for(int k = 1 ; k <= 2 ; k++)
				t.c[i][j] = (t.c[i][j]+x.c[i][k]*y.c[k][j])%mod;
	return t;
}
void quickpow(ll n){
	F.c[1][1] = F.c[1][2] = 1;
	A.c[1][1] = A.c[1][2] = A.c[2][1] = 1;
	while(n){
		if(n&1) F = F*A;
		A = A*A;
		n >>= 1;
	}
}
int main()
{
	
	ll x;
	cin >> x;
	if(x <= 2){ 
		cout << 1;
		return 0;
	} 
	quickpow(x-2);
	cout << F.c[1][1];
	
	
	return 0;
	
}

最大公约数和最小公倍数

欧几里得算法: g c d ( a , b ) = g c d ( a , a % b ) gcd(a,b)=gcd(a,a\%b) gcd(a,b)=gcd(a,a%b)

g c d ( p , q ) = x gcd(p,q)=x gcd(p,q)=x l c m ( p , q ) = y lcm(p,q)=y lcm(p,q)=y,则 p q = g c d ( p , q ) l c m ( p , q ) = x y pq=gcd(p,q)lcm(p,q)=xy pq=gcd(p,q)lcm(p,q)=xy

最大公约数和最小公倍数问题

题目描述

输入两个正整数 x 0 , y 0 x_0, y_0 x0,y0,求出满足下列条件的 P , Q P, Q P,Q 的个数:

  1. P , Q P,Q P,Q 是正整数。

  2. 要求 P , Q P, Q P,Q x 0 x_0 x0 为最大公约数,以 y 0 y_0 y0 为最小公倍数。

试求:满足条件的所有可能的 P , Q P, Q P,Q 的个数。

输入格式

一行两个正整数 x 0 , y 0 x_0, y_0 x0,y0

输出格式

一行一个数,表示求出满足条件的 P , Q P, Q P,Q 的个数。

样例 #1

样例输入 #1

3 60

样例输出 #1

4
//已知结论,只需要枚举p
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll x,y,ans;
int main()
{
	cin >> x >> y;
	ll t = x*y;
	for(ll i = 1 ; i*i <= t ; i ++)
		if(t%i==0 && __gcd(i,t/i)==x)
			ans += 2;
	if(x==y) ans--;
	cout << ans;
	return 0;
}

埃式筛法 O ( n l o g l o g ( n ) ) O(nloglog(n)) O(nloglog(n))

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e8+10;
bool vis[N];
int prim[6000010];
int cnt;
void Eratosthenes(ll n){
	for(ll i = 2 ; i <= n ; i ++)
	{
		if(!vis[i]){
			prim[++cnt] = i;
			for(ll j = i*i ; j <= n ; j +=i)
				vis[j] = 1;
		}
	}
}
int main()
{
	ll n;
	int q;
	cin >> n >> q;
	Eratosthenes(n);
	while(q--)
	{
		int x;
		cin >> x;
		cout << prim[x]<< endl;
	}
	return 0;
}

欧式筛法 O ( n ) O(n) O(n)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e8+10;
bool vis[N];
int prim[6000010];
int cnt;
void get_prim(ll n){
	for(int i = 2; i <= n ; i ++){
		if(!vis[i]) prim[++cnt] = i;
		for(int j = 1 ; 1LL*i*prim[j] <= n ; j ++)
		{
			vis[i*prim[j]] = 1;
			if(i%prim[j] == 0) break;
		}
	}
}
int main()
{
	ll n;
	int q;
	cin >> n >> q;
	get_prim(n);
	while(q--)
	{
		int x;
		cin >> x;
		cout << prim[x]<< endl;
	}
	return 0;
}

欧拉函数

定义 1 1 1~ n n n中与 n n n互质的数的个数成为欧拉函数,记为 φ ( n ) \varphi(n) φ(n)

例如: φ ( 1 ) = 1 \varphi(1)=1 φ(1)=1 φ ( 2 ) = 1 \varphi(2)=1 φ(2)=1 φ ( 3 ) = 2 \varphi(3)=2 φ(3)=2 φ ( 4 ) = 2 \varphi(4)=2 φ(4)=2 φ ( 5 ) = 4 \varphi(5)=4 φ(5)=4

性质

1.若 p p p是质数,则 φ ( p ) = p − 1 \varphi(p)=p-1 φ(p)=p1

2.若p是质数,则 φ ( p k ) = ( p − 1 ) p k − 1 \varphi(p^k)=(p-1)p^{k-1} φ(pk)=(p1)pk1

3.积性函数:若 g c d ( m , n ) = 1 gcd(m,n)=1 gcd(m,n)=1,即 m , n m,n m,n互质,则 φ ( m n ) = φ ( m ) φ ( n ) \varphi(mn)=\varphi(m)\varphi(n) φ(mn)=φ(m)φ(n)

计算公式
n = ∑ i = 1 s p i α i = p 1 α 1 p 2 α 2 ⋯ p s α s φ ( n ) = n × ∑ i = 1 s p i − 1 p i = n × p 1 − 1 p 1 × p 2 − 1 p 2 × ⋯ × p s − 1 p s n=\sum_{i=1}^sp_{i}^{\alpha_i}=p_1^{\alpha_1}p_2^{\alpha_2}\cdots p_s^{\alpha_s}\\ \varphi(n)=n\times\sum_{i=1}^s\frac{p_{i}-1}{p_i} =n\times\frac{p_1-1}{p1}\times\frac{p_2-1}{p_2}\times \cdots \times\frac{p_s-1}{p_s} n=i=1spiαi=p1α1p2α2psαsφ(n)=n×i=1spipi1=n×p1p11×p2p21××psps1

//试除法
int phi(int n){
	int res = n;
    for(int i = 2 ; i*i<=n ; i++){
        if(n%i == 0){
            res = res/i*(i-1);
            while(n%i == 0) n /= i;
        }
    }
    if(n>1) res = res/n*(n-1);
    return res;
}

线性欧拉函数

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+10;
int p[N], vis[N], cnt;
int phi[N];
void get_phi(int n){
	phi[1] = 1;
	for(int i = 2 ; i <= n ; i ++){
		if(!vis[i]){
			p[cnt++] = i;
			phi[i] = i-1;
		}
		for(int j = 0 ; i*p[j] <= n ; j ++){
			int m = i*p[j];
			vis[m] = 1;
			if(i%p[j] == 0){
				phi[m] = p[j]*phi[i];
				break;
			}else phi[m] = (p[j]-1)*phi[i];
		}
	}
}

约数定理

n = ∏ i = 1 s p i α i , 则 d ( n ) = ∏ i = 1 s ( α i + 1 ) n=\prod_{i=1}^sp_i^{\alpha_i},则d(n)=\prod_{i=1}^s(\alpha_i+1) n=i=1spiαi,d(n)=i=1s(αi+1)

const int N = 1e6 + 10;
int p[N], vis[N], cnt;
int a[N];//记录i的最小质因数的次数
int d[N];//记录i的约数个数
void get_d(int n){
    d[1] = 1;
    for(int i = 2 ; i <= n ; i++){
        if(!vis[i]){
            p[++cnt] = i;
            a[i] = 1; d[i] = 2;
        }
        for(int j = 1; i*p[j] <= n ; j++){
            int m = i*p[j];
            vis[m] = 1;
            if(i%p[j] == 0){
                a[m] = a[i] + 1;
                d[m] = d[i]/a[m]*(a[m]+1);
                break;
            }else{
                a[m] = 1; d[m] = d[i]*2;
            }
        }
    }
}

同余式

a ≡ b ( m o d   m ) a\equiv b(mod\ m) ab(mod m) ( a a a b b b对m同余) 例如 $8 \equiv2(mod \ 3) $

乘法逆元

a a a, b b b互质 ( a % b ≠ 0 ) (a\%b\neq0) (a%b=0),且满足同余方程 a x ≡ 1 ( m o d   b ) ax\equiv1(mod\ b) ax1(mod b),则称 x x x a a a b b b的乘法逆元,记作 a − 1 a^{-1} a1

例如: 8 x ≡ 1 ( m o d   5 ) 8x \equiv 1(mod\ 5) 8x1(mod 5),解得 x = 2 , 7 , 12... x=2,7,12... x=2,7,12...

费马小定理

p p p为质数,且 a , p a,p a,p互质,则 a p − 1 ≡ 1 ( m o d   p ) a^{p-1}\equiv1(mod\ p) ap11(mod p)

**问题:**给定两个数 a , p , p a,p,p a,p,p是质数,求 a a a p p p的乘法逆元

由费马小定理, a p − 1 ≡ 1 ( m o d   p ) a^{p-1}\equiv1(mod\ p) ap11(mod p),得 a × a p − 2 ≡ 1 ( m o d   p ) a\times a^{p-2} \equiv1(mod\ p) a×ap21(mod p),则 a a a p p p的乘法逆元为 a p − 2 a^{p-2} ap2

ll quickpow(ll a,ll b,ll p){
    ll res = 1;
    while(b){
        if(b&1) res = res*a%p;
        a = a*a%p;
        b >>= 1;
    }
    return res;
}
int main(){
    cin >> a >> p;
    if(a%p)	cout << qucikpow(a,p-2,p);
}

欧拉定理

欧拉函数 1 1 1~ n n n中与 n n n互质的数的个数成为欧拉函数,记为 φ ( n ) \varphi(n) φ(n)
φ ( n ) = n × ∑ i = 1 s p i − 1 p i = n × p 1 − 1 p 1 × p 2 − 1 p 2 × ⋯ × p s − 1 p s \varphi(n)=n\times\sum_{i=1}^s\frac{p_{i}-1}{p_i} =n\times\frac{p_1-1}{p1}\times\frac{p_2-1}{p_2}\times \cdots \times\frac{p_s-1}{p_s} φ(n)=n×i=1spipi1=n×p1p11×p2p21××psps1
欧拉定理

g c d ( a , m ) = 1 gcd(a,m)=1 gcd(a,m)=1,则 a φ ( m ) ≡ 1 ( m o d   m ) a^{\varphi(m)} \equiv1(mod\ m) aφ(m)1(mod m)

m m m为质数时,由于 φ ( m ) = m − 1 \varphi(m)=m-1 φ(m)=m1,带入欧拉定理,可得到费马小定理 a m − 1 ≡ 1 ( m o d   m ) a^{m-1}\equiv1(mod\ m) am11(mod m)

扩展欧拉定理
a b ≡ { a b , b < φ ( m ) , ( m o d   m ) a b   m o d   φ ( m ) + φ ( m ) , b ≥ φ ( m ) , ( m o d   m ) a^b \equiv\left\{ \begin{array}{l} a^b,&b<\varphi(m),(mod\ m)\\ a^{b\ mod\ \varphi(m)+\varphi(m)},& b\geq\varphi(m),(mod\ m) \end{array} \right. ab{ab,ab mod φ(m)+φ(m),b<φ(m),(mod m)bφ(m),(mod m)

【模板】扩展欧拉定理
题目描述

给你三个正整数, a , m , b a,m,b a,m,b,你需要求: a b   m o d   m a^b \bmod m abmodm

输入格式

一行三个整数, a , m , b a,m,b a,m,b

输出格式

一个整数表示答案

样例 #1

样例输入 #1

2 7 4

样例输出 #1

2

样例 #2

样例输入 #2

998244353 12345 98765472103312450233333333333

样例输出 #2

5333

提示

注意输入格式, a , m , b a,m,b a,m,b 依次代表的是底数、模数和次数

【样例 1 1 1 解释】
2 4   m o d   7 = 2 2^4 \bmod 7 = 2 24mod7=2
【数据范围】
对于 100 % 100\% 100% 的数据, 1 ≤ a ≤ 1 0 9 1\le a \le 10^9 1a109 1 ≤ b ≤ 1 0 20000000 , 1 ≤ m ≤ 1 0 8 1\le b \le 10^{20000000},1\le m \le 10^8 1b10200000001m108

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
char s[20000050];
int a,b,m,phi,flag;
int get_phi(int m){
	int res = m;
	for(int i = 2 ; i*i <= m ; i++){
		if(m%i == 0){
			res = res/i*(i-1);
			while(m%i == 0) m /= i;
		}
	}
	if(m > 1) res = res/m*(m-1);
	return res;
}
int depow(int phi){
	int b = 0;
	for(int i = 0 ; s[i] ; i++){
		b = b*10+(s[i]-'0');
		if(b >= phi) flag = 1, b %= phi;
	}
	if(flag) b += phi;
	return b;
}
int quickpow(ll a,int b){
	ll res = 1;
	while(b){
		if(b&1) res = res*a%m;
		a = a*a%m;
		b >>= 1;
	}
	return res;
}
int main()
{
	cin >> a >> m >> s;
	phi = get_phi(m);
	b = depow(phi);
	int ans = quickpow(a,b);
	cout << ans;
	return 0;
}

威尔逊定理

( p − 1 ) ! ≡ − 1 ( m o d   p ) (p-1)!\equiv-1(mod\ p) (p1)!1(mod p) p p p为质数的充分必要条件

推论

1.若 p p p是质数,则 ( p − 1 ) ! + 1 ≡ ( m o d   p ) (p-1)!+1\equiv(mod\ p) (p1)!+1(mod p)

2.若 p p p是大于 4 4 4的合数,则 ( p − 1 ) ! ≡ 0 ( m o d   p ) (p-1)!\equiv0(mod\ p) (p1)!0(mod p)

裴蜀定理

一定存在整数 x , y x,y x,y,满足 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)

推广:

一定存在整数 x , y x,y x,y,满足 a x + b y = g c d ( a , b ) × n ax+by=gcd(a,b)\times n ax+by=gcd(a,b)×n

再推广:

一定存在整数 X 1 . . . X i X_1...X_i X1...Xi,满足 ∑ i = = 1 n A i X i = g c d ( A 1 , A 2 , . . . , A n ) \sum_{i==1}^nA_iX_i=gcd(A_1,A_2,...,A_n) i==1nAiXi=gcd(A1,A2,...,An)

注意:求gcd时可带入绝对值求

posted @ 2023-12-14 10:51  xde_yt  阅读(4)  评论(0编辑  收藏  举报  来源