classSolution { public: intcountPrimes(int n){ vector<int> primes; vector<int> isPrime(n, 1); for (int i = 2; i < n; ++i) { if (isPrime[i]) { primes.push_back(i); } for (int j = 0; j < primes.size() && i * primes[j] < n; ++j) { isPrime[i * primes[j]] = 0; if (i % primes[j] == 0) { break; } } } return primes.size(); } };
1 最大公约数(GCD)
1.1 欧几里得算法
gcd(m,n)=gcd(n,m mod n)
假设x是m,n的最大公约数,且m大于n(m小于n时,上式实现两个数的交换)
m=(m/n)*n+m%n( / 表示整除)
n=(n/x)*x
则,则(m/n)*n有约数x,又m有约数x,则m%n也可以被x整除
#include<iostream> usingnamespace std; intEuclid(int m, int n) { while (n) { int t = m % n; m = n; n = t; } return m; } intmain() { cout << Euclid(60, 24) << endl; }
1.2 连续整数检测算法
从m、n中较小的数开始查找,直到找到可以被m、n都整除的数
#include<iostream> usingnamespace std; intgcd(int m, int n) { int t = min(m, n); while (m % t != 0 || n % t != 0) --t; return t; } intmain() { cout << gcd(60, 24) << endl; }
#include<iostream> #include<vector> usingnamespace std; //埃拉托色尼筛选法,产生一个不大于给定整除n的连续质数序列 voidSieve(int n, vector<int> &isPrime) { for (int i = 2; i * i <= n; ++i) { if (isPrime[i]) { int t = i * i; while (t <= n) { isPrime[t] = 0; t = t + i; } } } } intgcd(vector<int> &isPrime, int m, int n) { int result = 1; for (int i = 2; i <= n; ++i) { //如果i是质数 if (isPrime[i]) { while (m % i == 0 && n % i == 0) { m = m / i; n = n / i; result *= i; } } } return result; } intmain() { int m, n; cin >> m >> n; vector<int> isPrime(min(m, n) + 1, 1); //记录较小数的质数序列 // cout << isPrime.size() << endl; Sieve(min(m, n), isPrime); cout << gcd(isPrime, max(m, n), min(m, n)) << endl; }
2 最小公倍数(LCM)
$$
LCM(m,n)=\frac{m*n}{GCD(m,n)}
$$
3 容斥原理
4 快速幂
//计算a^b%m inthelper(int a,int b,int m){ int res=1; int factor=a; while(b){ if(b&1){ res=(res*factor)%m; } factor=factor*factor%m; b=(b>>1); } return res; }