Hanwan Space

数论的一些板子


这篇 Blog 记录了一些数论代数的板子,以便不时之需。

线性筛素数

cpp
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e7 + 3;
bool isprime[MAXN];
void sieve(int n){
	memset(isprime, true, sizeof(isprime));
	isprime[0] = isprime[1] = false;
	for (int i = 2; i <= n; i++) {
		if (isprime[i])
			for (int j = i*2; j <= n; j += i) isprime[j] = false;
	}
}
int main(){
	int n, m, x;
	cin >> n >> m;
	sieve(n);
	while (m--) {
		cin >> x;
		if (isprime[x]) cout << "Yes" << endl;
		else cout << "No" << endl;
	}
	return 0;
}

扩展欧几里得算法

求解不定方程 ax+by=gcd(a,b),abax+by=\gcd(a,b),a\geq b

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

乘法逆元

设正整数模 mma\forall a 满足 (a,m)=1(a,m)=1b\exists b 满足 ab1(mod m)ab\equiv 1(\bmod\ m),称 bb 为模 mm 意义下 aa 的逆元。 求逆元只需解线性同余方程 ab+mt=1ab+mt=1 即可。

cpp
#include <bits/stdc++.h>
using namespace std;
int n, p;
void exgcd(int a, int b, int &x, int &y) {
	if (!b) x = 1, y = 0;
	else {
		exgcd(b, a % b, y, x);
		y -= a / b * x;
	}
}
int main() {
	scanf("%d%d", &n, &p);
	for (int i = 1; i <= n; i++) {
		int x = 0, y = 0;
		exgcd(i, p, x, y);
		x = (x + p) % p;
		printf("%d\n", x);
	}
	return 0;
}

线性筛欧拉

φ(n)\varphi(n)表示 1 到 n 中与 n 互质的整数的个数。 φ(pk)=pkpk1=(p1)pk1\varphi(p^k)=p^k-p^{k-1}=(p-1)p^{k-1}

cpp
notprime[1] = true;
for (int i = 2; i <= n; i++) {
	if (!notprime[i]) {
		prime[++psz] = i;
		phi[i] = i - 1;
	}
	for (int j = 1; j <= psz; j++) {
		int k = i * prime[j];
		if (k > n) break;
		notprime[i * prime[j]] = true;
		if (i % prime[j] == 0) {
			phi[k] = phi[i] * prime[j];
			break;
		} else {
			phi[k] = phi[i] * (prime[j] - 1);
		}
	}
}

  • 板子
  • 数论
© hawa130转载请注明出处
License: CC BY-NC-SA 4.0

上一篇

线性代数的一些板子

下一篇

Blog 搭建笔记