[关闭]
@TaoSama 2017-01-23T23:22:59.000000Z 字数 3640 阅读 1417

2: Basic Math Algos

Learning-ACM


GCD

To Prove





  1. //__gcd(a, b)
  2. int gcd(int a, int b){
  3. return b == 0 ? a : gcd(b, a % b);
  4. }

Complexity





LCM

  1. int lcm(int a, int b){
  2. return a / gcd(a, b) * b;
  3. }

Exgcd


  1. //ax+by=gcd(a, b)
  2. LL exgcd(LL a, LL b, LL& x, LL& y) {
  3. LL d = a;
  4. if(!b) x = 1, y = 0;
  5. else {
  6. d = exgcd(b, a % b, y, x);
  7. y = (a / b) * x;
  8. }
  9. return d;
  10. }
  11. //求二元一次方程x最小非负解
  12. LL solve(LL a, LL b, LL c) {
  13. LL x, y, g = exgcd(a, b, x, y);
  14. if(c % g) return -1;
  15. x *= c / g;
  16. x = (x % b + b) % (b / g);
  17. return x;
  18. }

埃氏筛法

  1. //O(nloglogn)
  2. bool notPrime[C];
  3. vector<int> prime;
  4. //int p[C / 10], ps;
  5. for(int i = 2; i < C; ++i){
  6. if(notPrime[i]) continue;
  7. prime.push_back(i);
  8. for(int j = i + i; j < C; j += i)
  9. notPrime[j] = true;
  10. }

欧拉筛 (线性筛)

  1. // O(n)
  2. bool notPrime[C];
  3. vector<int> prime;
  4. for(int i = 2; i < C; ++i){
  5. if(!notPrime[i]) prime.push_back(i);
  6. for(int j = 0; j < prime.size() && i * prime[j] < C; ++j){
  7. notPrime[i * prime[j]] = true;
  8. if(i % prime[j] == 0) break;
  9. }
  10. }





质因子分解


  1. // O(sqrt(n))
  2. void factorize(int n){
  3. vector<int> factors;
  4. for(int i = 2; i * i <= n; ++i) {
  5. if(n % i == 0) {
  6. factors.push_back(i);
  7. while(n % i == 0) n /= i;
  8. if(n == 1) break;
  9. }
  10. }
  11. if(n != 1) factors.push_back(n);
  12. return factors;
  13. }
  14. void factorize(int n){
  15. vector<int> factors;
  16. for(int i = 0; i < primes.size() && primes[i] * primes[i] <= n; ++i){
  17. if(n % primes[i] == 0) {
  18. factors.push_back(primes[i]);
  19. while(n % primes[i] == 0) n /= primes[i];
  20. if(n == 1) break;
  21. }
  22. }
  23. if(n != 1) factors.push_back(n);
  24. return factors;
  25. }

约数分解


  1. void decomposite(int n){
  2. vector<int> divisors;
  3. for(int i = 2; i * i <= n; ++i){
  4. divisors.push_back(i);
  5. if(i * i != n) divisors.push_back(n / i);
  6. }
  7. return divisors;
  8. }
  9. vector<int> divisors[N];
  10. void init(){
  11. for(int i = 2; i < N; ++i){
  12. for(int j = i + i; j < N; j += i)
  13. divisors[j].push_back(i);
  14. }
  15. }

逆元

逆元详解,点击直达

a * x % m == 1 % m

  1. //MOD必须是素数
  2. [1, MOD) MOD的逆元
  3. inv[1] = 1;
  4. for(int i = 2; i < MOD; ++i)
  5. inv[i] = (MOD - MOD / i) * inv[MOD % i] % MOD;
  1. int inv(int a, int m){
  2. int x, y, g = exgcd(a, m, x, y);
  3. if(g != 1) return -1;
  4. return (a + m) % m;
  5. }
  1. //O(logn)
  2. int quickPow(int x, int n){
  3. if(n == 0) return 1;
  4. if(n & 1) return x * quickPow(x, n - 1);
  5. else {
  6. int ret = quick(x, n / 2); // (x^(n/2))^2 = x^n
  7. return ret * ret;
  8. }
  9. }
  10. //O(logn)
  11. int quickPow(int x, int n){
  12. int ret = 1;
  13. for(; n; n >>= 1){
  14. if(n & 1) ret = ret * x;
  15. x = x * x;
  16. }
  17. return ret;
  18. }
  19. int inv(int x, int m){
  20. if(m is not a prime) return -1;
  21. return quickPow(x, m - 2);
  22. }

组合数



  1. int fact[N], invFact[N];
  2. void init(){
  3. fact[0] = 1 = invFact[0] = 1;
  4. for(int i = 1; i < N; ++i) {
  5. fact[i] = fact[i - 1] * i % MOD;
  6. invFact[i] = inv(fact[i], MOD);
  7. }
  8. }
  9. //n <= MOD, m <= MOD, MOD不是很大
  10. int C(int n, int m){
  11. return fact[n] * invFact[m] % MOD * invFact[n - m] % MOD;
  12. }
  13. //m比较小
  14. int C(int n, int m){
  15. int ret = 1;
  16. //C(n,m)=C(n,n-m)
  17. m = min(m, n - m);
  18. for(int i = 0; i < m; ++i){
  19. ret *= (n - i);
  20. ret /= (i + 1);
  21. }
  22. return ret;
  23. }
  24. int C(int n, int m){
  25. int up = 1, dw = 1;
  26. //C(n,m)=C(n,n-m)
  27. m = min(m, n - m);
  28. for(int i = 0; i < m; ++i){
  29. up *= (n - i);
  30. dw *= (i + 1);
  31. }
  32. dw = inv(dw, MOD);
  33. return up * dw % MOD;
  34. }
  35. //C(n,m) = C(n-1,m)+C(n-1,m-1)
  36. // 1
  37. // 1 2 1
  38. // 1 3 3 1
  39. //n和m都不大
  40. int C[N][N];
  41. for(int i = 0; i < N; ++i)
  42. for(int j = 0; j < N; ++j)
  43. if(j == 0 || j == i) C[i][j] = 1;
  44. else C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注