【数论 】
五、数论
文章目录
快速幂
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 的个数:
-
P , Q P,Q P,Q 是正整数。
-
要求 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)=p−1
2.若p是质数,则 φ ( p k ) = ( p − 1 ) p k − 1 \varphi(p^k)=(p-1)p^{k-1} φ(pk)=(p−1)pk−1
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=1∑spiαi=p1α1p2α2⋯psαsφ(n)=n×i=1∑spipi−1=n×p1p1−1×p2p2−1×⋯×psps−1
//试除法
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=1∏spiαi,则d(n)=i=1∏s(α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) a≡b(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) ax≡1(mod b),则称 x x x为 a a a模 b b b的乘法逆元,记作 a − 1 a^{-1} a−1
例如: 8 x ≡ 1 ( m o d 5 ) 8x \equiv 1(mod\ 5) 8x≡1(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) ap−1≡1(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) ap−1≡1(mod p),得 a × a p − 2 ≡ 1 ( m o d p ) a\times a^{p-2} \equiv1(mod\ p) a×ap−2≡1(mod p),则 a a a模 p p p的乘法逆元为 a p − 2 a^{p-2} ap−2
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=1∑spipi−1=n×p1p1−1×p2p2−1×⋯×psps−1
欧拉定理
若 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)=m−1,带入欧拉定理,可得到费马小定理 a m − 1 ≡ 1 ( m o d m ) a^{m-1}\equiv1(mod\ m) am−1≡1(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
1≤a≤109,
1
≤
b
≤
1
0
20000000
,
1
≤
m
≤
1
0
8
1\le b \le 10^{20000000},1\le m \le 10^8
1≤b≤1020000000,1≤m≤108。
#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) (p−1)!≡−1(mod p)是 p p p为质数的充分必要条件
推论
1.若 p p p是质数,则 ( p − 1 ) ! + 1 ≡ ( m o d p ) (p-1)!+1\equiv(mod\ p) (p−1)!+1≡(mod p)
2.若 p p p是大于 4 4 4的合数,则 ( p − 1 ) ! ≡ 0 ( m o d p ) (p-1)!\equiv0(mod\ p) (p−1)!≡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时可带入绝对值求