下笔春蚕食叶声。

简单数论

好像不太简单/ll

1.gcd&exgcd

1.gcd: 辗转相除。

int gcd(int x,int y){
    if(y==0) return x;
    return gcd(y,x%y);
}

2.exgcd:
裴蜀定理:对于任意正整数a,b,一定存在非零数对(x,y),满足ax+by=gcd(a,b).
\(gcd(a,b)=gcd(b,a\%b)\)
\(x',y'\)是方程$ by'+ (a % b) x' =gcd(b,a%b)$ 的解
\(by'+ (a \% b) x' =gcd(a,b)\)
\(by'+ (a-b(a/b)) x' =gcd(a,b)\)
\(ax'+by'-b(a/b)x' =gcd(a,b)\)
\(ax'+b(y'-(a/b)x') =gcd(a,b)\)
\(x=x',y=y'-(a/b)x'\)

void exgcd(int a, int b, int &x, int &y, int &d) {
	if(b == 0) x = 1, y = 0, d = a;
	else exgcd(b, a % b, y, x, d), y -= a / b * x;
	return;
}

附一个极清晰的解释

2.欧拉函数和欧拉定理

\(\phi(n)\) 表示小于等于 \(n\) 且与 \(n\) 互质的数的个数。
\(\phi(n)=n\prod_{p|n} (1-\frac 1 p)\)
特别地,\(\phi(1)=1\).
感性理解一下。证明不会

在n以内所有与n互素的所有数之和为n*Φ(n)/2。

1.\(O(\sqrt n)\) 筛质因数求欧拉函数。
@[墨染空] 的代码

int phi = x;
for(int j = 2; j * j <= x; j++){
    if(x % j == 0){
            phi = phi / j * (j - 1);
            while(x % j == 0) x /= j; 
        }
}
if(x > 1) phi = phi / x * (x - 1);

2.\(O(n)\) 线性筛出\(1-n\)\(\phi (i)\)
由定义可知,\(\phi (p) =p-1\)
如果\(p|x,\phi (px)=p \phi(x)\)
否则,\(\phi (px)=(p-1) \phi(x)\)
证明不会
这份是我的代码

phi[1]=1;
for(int i=2;i<=n;i++){
	if(!vis[i]) p[++cnt]=i,phi[i]=i-1;
	for(int j=1;j<=cnt&&i*p[j]<=n;j++){
		vis[i*p[j]]=1;
		if(i%p[j]==0){
			phi[i*p[j]]=phi[i]*p[j];
			break;
		}
		phi[i*p[j]]=phi[i]*(p[j]-1);
	}
}

欧拉定理:当 \(gcd(a, n) = 1\)\(a^{\phi (n)} \equiv 1 \bmod n\)
证明:
\(1\)\(n\) 的数中有 \(\phi (n)\) 个数与 \(n\) 互质,设为 \(x_i\)
\(m_i=a\times x_i\)

下面证明两个性质

  1. \(\forall i, j\in [1,\phi (n)],m_i\not\equiv m_j \bmod n\)
    反证:

\[假设m_a \equiv m_b \bmod n\\ m_a - m_b = n\times k\\ a\times(x_a-x_b)=n\times k\\ \because gcd(a,n)=1 \therefore x_a - x_b \equiv 0 \bmod n\\ 又\because x_a,x_b\le n 并且 x_a \neq x_b\\ \therefore x_a - x_b < 0\\ 矛盾 \]

  1. \(\forall i\in [1,\phi (n)], gcd(m_i \bmod n, n) = 1\)

\[已知 m_i = a \times x_i\\ 又\because gcd(a,n)=1,gcd(x_i, n)=1\\ \therefore gcd(m_i, n) = 1\\ \therefore gcd(m_i \bmod n, n) = 1 \]

可知集合 \(m\)\(x\) 相同(无序)

\[\prod m_i \equiv \prod x_i \bmod n\\ a^{\phi (n)} \times \prod x_i \equiv \prod x_i \bmod n\\ (a^{\phi (n)} - 1) \times \prod x_i \equiv 0 \bmod n\\ a^{\phi (n)} \equiv 1 \bmod n \]

扩展欧拉定理:

\[a^c \equiv \begin{cases} a^{c \bmod \varphi(m)} &\gcd(a,m)=1 \\ a^c &\gcd(a,m) \neq 1,c<\varphi(m) \\ a^{\left(c \bmod \varphi(m)\right)+\varphi(m)} &\gcd(a,m) \neq 1,c \geq \varphi(m) \end{cases} \pmod m \]

case 1:
由欧拉定理显然
case 2:
无需证明
case 3:

\[只需证明 a 的任意一个质因子都满足 p_i ^c\equiv p_i ^ {(c\bmod \phi(n)) + \phi(n)} \bmod n\\ 令n = s \times p^r, gcd(s,p)=1\\ \because p^{\phi (s)} \equiv 1 \bmod s,gcd(s,p)=1\\ 那么 \phi (s) | \phi (n)\\ 即p^{\phi (n)} \equiv 1 (\bmod s)\\ p^{\phi (n) + r} \equiv p^r (\bmod s) \\那么 p^c \equiv p^{c-r+r} \equiv p^{\phi (n) + c} \bmod n, c \ge r \\显然 r \le \phi (n) \\因此 p^c \equiv p^{\phi (n) + c} \bmod n, c\ge \phi (n) \\p^c \equiv p^{c \bmod \phi(n) +\phi (n)} \bmod n \]

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mkp make_pair
#define pb push_back
#define PII pair<int, int>
#define PLL pair<ll, ll>
const int N = 2e7 + 10, M = 1e8; 
char s[N];
int calc(int x) {
	int ret = x;
	for(int i = 2; i * i <= x; i++) {
		if(x % i == 0) ret /= i, ret *= (i - 1);
		while(x % i == 0) x /= i;
	}
	if(x != 1) ret /= x, ret *= (x - 1);
	return ret;
}
int power(int a, int b, int mod) {
	int ret = 1;
	while(b) {
		if(b & 1) ret = 1ll * ret * a % mod;
		a = 1ll * a * a % mod; b >>= 1;
	}
	return ret;
}
int main(){
	int a, b = 0, m;
	scanf("%d%d%s", &a, &m, s + 1);
	int t = calc(m);
	int len = strlen(s + 1);
	bool fl = 0;
	for(int i = 1; i <= len; i++) {
		b = b * 10 + s[i] - '0';
		if(b >= t) fl = 1; 
		b %= t;
	}
	if(fl) printf("%d\n", power(a, b + t, m));
	else printf("%d\n", power(a, b, m));
	return 0;
}

3.逆元

两种。

1.费马小定理(p为质数)
\(a^{p-1} \equiv 1 \bmod p\)
\(a^{p-2} \equiv \frac 1 p \bmod p\)
\(inv(x)=x^{p-2} \bmod p\)
快速幂。

2.exgcd
\(xinv(x) \equiv 1 \bmod p\)
\(s=inv(x)\)
\(xs \equiv 1 \bmod p\)
\(xs+pt=1\)
exgcd。

还有线性的。

iv[0] = iv[1] = 1;
for(int i = 2; i <= n; i++) 
	iv[i] = 1ll * iv[p % i] * (p - p / i) % p;

4. 欧拉筛

线性筛素数。在埃氏筛法的基础上,让每个合数只被它的最小质因子筛选一次。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mkp make_pair
#define pb push_back
#define PII pair<int, int>
#define PLL pair<ll, ll>
const int N = 1e8 + 10;
int n, q, p[N], cnt;
bool vis[N];
void init() {
	for(int i = 2; i <= n; i++) {
		if(!vis[i]) p[++cnt] = i;
		for(int j = 1; j <= cnt && p[j] * i <= n; j++) {
			vis[p[j] * i] = 1;
			if(i % p[j] == 0) break;
		}
	}
	return;
}
int main(){
	scanf("%d%d", &n, &q);
	init();
	for(int i = 1, k; i <= q; i++) 
		scanf("%d", &k), printf("%d\n", p[k]);
	return 0;
}

5.crt&excrt

crt不会 反正excrt挺好的。
模板题
现在有n个形如\(x \equiv a_i \pmod {b_i}\)的方程
假设前k-1个方程的最小正整数解是\(ans_{k-1},\)
\(M=lcm(b_1,b_2,……,b_{k-1})\)
\(ans_k=ans_{k-1}+xM(x为整数)\)
\(ans_{k-1}+xM \equiv a_k \pmod {b_k}\)
\(Mx\equiv {{a_k}-{ans_{k-1}}} \pmod {b_k}\)
\(Mx+{b_k}y={{a_k}-{ans_{k-1}}}\)
exgcd。
题目的a,b读入是反的,注意。 还有记得开longlong。

/*
exCRT 正常做法。 
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mkp make_pair
#define pb push_back
#define PII pair<int, int>
#define PLL pair<ll, ll>
const int N = 1e5 + 10;
int n; ll ai[N], bi[N];
void exgcd(ll a, ll b, ll &x, ll &y, ll &d) {
	if(b == 0) x = 1, y = 0, d = a;
	else exgcd(b, a % b, y, x, d), y = y - a / b * x;
	return;
}
ll gcd(ll x, ll y) {
	return (y == 0) ? x : gcd(y, x % y);	
}
ll mul(ll x, ll y, ll mod) {
	ll ret = 0;
	while(y) {
		if(y & 1) ret = (ret + x) % mod;
		x = (x + x) % mod; y >>= 1;
	}
	return ret;
}
int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) 
		scanf("%lld%lld", &ai[i], &bi[i]);
	ll M = 1, ans = 0;
	for(int i = 1; i <= n; i++) {
		ll z = (bi[i] % ai[i] + ai[i] - ans % ai[i]) % ai[i];
		ll x, y, d; exgcd(M, ai[i], x, y, d);
		if(z % d) return puts("-1"), 0;
		x = mul(x, z / d, ai[i] / d);
		ans = ans + M * x;
		M = M * (ai[i] / d);
		ans = (ans % M + M) % M;
	}
	printf("%lld\n", ans);
	return 0;
}

正常版本的CRT的题解

/*
CRT 正常做法。 
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mkp make_pair
#define pb push_back
#define PII pair<int, int>
#define PLL pair<ll, ll>
const int N = 15;
int n, a[N], b[N];
void exgcd(ll a, ll b, ll &x, ll &y, ll &d) {
	if(b == 0) x = 1, y = 0, d = a;
	else exgcd(b, a % b, y, x, d), y = y - a / b * x;
	return;
}
ll gcd(ll x, ll y) {
	return (y == 0) ? x : gcd(y, x % y);	
}
int main(){
	scanf("%d", &n);
	ll M = 1;
	for(int i = 1; i <= n; i++) {
		scanf("%d%d", &a[i], &b[i]);
		M = M * a[i] / gcd(a[i], M);
	}
	ll ans = 0;
	for(int i = 1; i <= n; i++) {
		ll x, y, d, m = M / a[i]; exgcd(m, a[i], x, y, d);
		x = (x % a[i] + a[i]) % a[i];
		ans = (ans + 1ll * b[i] * m % M * x % M) % M;
	}
	printf("%lld\n", ans);
	return 0;
}

6.威尔逊定理

威尔逊定理

\[(n-1)!\equiv -1 (\bmod n) \Leftrightarrow n>1,n为素数 \]

\((n-1)! \equiv -1 \bmod n\) 推出 \(n>1,n\)为素数
如果 \(n>1\) 且非质数,一定有一个 \(\le \sqrt n\) 的因子。取最小的非 1 因子 \(x\)
如果 \(x<\sqrt n\) ,显然可以用 \((n-1)!\) 组合出 \(n\) (它和 \(\frac n {x}\)
如果 \(x=\sqrt n\)

  • 对于 \(\sqrt n=2\) 成立。
  • \(\sqrt n>2\)\(\sqrt n ·2<n\) 一定能取出另一个 \(\sqrt n\) 因子。
    所以非质数无法组成。

对于质数,余数分别是 \(1,2,3,4,...,n-1\) 。因为一个数只有一个逆元,所以要么 \(x\)\(y\) 配对,要么 \(x^2 \equiv 1 \bmod n\)
显然 \(n=2\) 时成立。
\(n>2\) 时,考虑哪些 \(x=y\)
\(x^2\equiv 1 \bmod n\)
\(x_1=1,x_2=n-1\)
剩下的两两配对即可。

posted @ 2020-11-02 07:32  ACwisher  阅读(140)  评论(0编辑  收藏  举报