github.com/zhiqiangxu/util@v0.0.0-20230112053021-0a7aee056cd5/math/divisor.go (about) 1 package math 2 3 import "math/big" 4 5 func DivCount(n int) int { 6 7 if n <= 0 { 8 panic("invalid input") 9 } 10 if n == 1 { 11 return 1 12 } 13 14 // store numbers in range [2,n] 15 numbers := make([]bool, n-1) 16 for i := range numbers { 17 numbers[i] = true 18 } 19 20 // sieve method for prime calculation 21 for i, v := range numbers { 22 p := i + 2 23 if v { 24 for j := i + p; j <= n-2; j += p { 25 numbers[j] = false 26 } 27 } 28 // if n can factor, then there's at least one <= sqrt(n) 29 if p*p >= n { 30 break 31 } 32 } 33 34 // Traversing through all prime numbers 35 total := 1 36 for i, v := range numbers { 37 if v { 38 // calculate number of divisor 39 // with formula total div = 40 // (p1+1) * (p2+1) *.....* (pn+1) 41 // where n = (a1^p1)*(a2^p2).... 42 // *(an^pn) ai being prime divisor 43 // for n and pi are their respective 44 // power in factorization 45 count := 0 46 p := i + 2 47 for n%p == 0 { 48 n /= p 49 count++ 50 } 51 if count > 0 { 52 total *= 1 + count 53 } 54 } 55 } 56 57 return total 58 } 59 60 // AbelGroups returns the # of abel groups of order n 61 // it's based on the fundamental theory of algebra that 62 // every finitely generated abel group is isomorphic to 63 // direct sum of prime-power cyclic groups. 64 func AbelGroups(n int) *big.Int { 65 if n <= 0 { 66 panic("invalid input") 67 } 68 if n == 1 { 69 return big.NewInt(1) 70 } 71 72 // store numbers in range [2,n] 73 numbers := make([]bool, n-1) 74 for i := range numbers { 75 numbers[i] = true 76 } 77 78 // sieve method for prime calculation 79 for i, v := range numbers { 80 p := i + 2 81 if v { 82 for j := i + p; j <= n-2; j += p { 83 numbers[j] = false 84 } 85 } 86 // if n can factor, then there's at least one <= sqrt(n) 87 if p*p >= n { 88 break 89 } 90 } 91 92 // Traversing through all prime numbers 93 total := big.NewInt(1) 94 for i, v := range numbers { 95 if v { 96 count := 0 97 p := i + 2 98 for n%p == 0 { 99 n /= p 100 count++ 101 } 102 if count > 0 { 103 total.Mul(total, Partition(count)) 104 } 105 } 106 } 107 108 return total 109 }