C++数论基础
·
数论是数学的一个分支,研究整数的性质和关系。在C++中,数论算法常用于解决竞赛编程、密码学等问题。以下是一些常见的数论概念及其C++实现。
素数判断
素数是指大于1的自然数,除了1和它本身外没有其他因数。
bool isPrime(int n) {
if (n <= 1) return false;
for (int i = 2; i * i <= n; ++i) {
if (n % i == 0) return false;
}
return true;
}
埃拉托斯特尼筛法
用于快速生成一定范围内的所有素数。
void sieveOfEratosthenes(int n) {
vector<bool> isPrime(n + 1, true);
isPrime[0] = isPrime[1] = false;
for (int i = 2; i * i <= n; ++i) {
if (isPrime[i]) {
for (int j = i * i; j <= n; j += i) {
isPrime[j] = false;
}
}
}
// 打印所有素数
for (int i = 2; i <= n; ++i) {
if (isPrime[i]) cout << i << " ";
}
}
最大公约数(GCD)
使用欧几里得算法计算两个数的最大公约数。
int gcd(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
C++17及以上版本提供了内置的std::gcd函数。
最小公倍数(LCM)
两个数的最小公倍数可以通过它们的最大公约数计算得出。
int lcm(int a, int b) {
return (a / gcd(a, b)) * b;
}
模运算
模运算在数论中非常重要,常用于处理大数问题。
-
加法取模
$(a + b) \mod m = (a \mod m + b \mod m) \mod m$ -
乘法取模
$(a \times b) \mod m = (a \mod m \times b \mod m) \mod m$ -
快速幂取模
计算$a^b \mod m$的高效方法。
long long fastPowMod(long long a, long long b, long long m) {
long long res = 1;
a = a % m;
while (b > 0) {
if (b & 1) res = (res * a) % m;
a = (a * a) % m;
b >>= 1;
}
return res;
}
扩展欧几里得算法
用于求解方程$ax + by = \gcd(a, b)$的整数解$(x, y)$。
int extendedGcd(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int x1, y1;
int g = extendedGcd(b, a % b, x1, y1);
x = y1;
y = x1 - (a / b) * y1;
return g;
}
模逆元
模逆元是指对于整数$a$和模数$m$,找到整数$x$使得$ax \equiv 1 \mod m$。
int modInverse(int a, int m) {
int x, y;
int g = extendedGcd(a, m, x, y);
if (g != 1) return -1; // 逆元不存在
return (x % m + m) % m; // 确保结果为正值
}
中国剩余定理
用于解决一组同余方程:
$x \equiv a_1 \mod m_1$
$x \equiv a_2 \mod m_2$
...
$x \equiv a_n \mod m_n$
int chineseRemainder(vector<int> &a, vector<int> &m) {
int n = a.size();
int M = 1;
for (int i = 0; i < n; ++i) M *= m[i];
int res = 0;
for (int i = 0; i < n; ++i) {
int Mi = M / m[i];
int inv = modInverse(Mi, m[i]);
res = (res + a[i] * Mi * inv) % M;
}
return res;
}
组合数计算
组合数$C(n, k)$表示从$n$个元素中取$k$个的组合数,可以通过动态规划或公式计算。
int comb(int n, int k) {
if (k > n) return 0;
if (k == 0 || k == n) return 1;
return comb(n - 1, k - 1) + comb(n - 1, k);
}
对于大数取模的组合数,通常需要预计算阶乘和逆阶乘。
欧拉函数
欧拉函数$\phi(n)$表示小于或等于$n$的正整数中与$n$互质的数的个数。
int eulerPhi(int n) {
int res = n;
for (int p = 2; p * p <= n; ++p) {
if (n % p == 0) {
while (n % p == 0) n /= p;
res -= res / p;
}
}
if (n > 1) res -= res / n;
return res;
}
以上是C++中常见的数论算法实现,涵盖了素数、GCD、模运算、组合数等核心内容。这些算法在竞赛编程和实际应用中非常有用。
更多推荐
所有评论(0)