质数与约数
什么是质数
在大于1的整数中,约数只有1和本身,那么这个数就是质数,或者叫素数。
质数的判定
试除法 O(sqrt(n)),当然对于约数是成对出现即(d, x/d), 因此对于最大的约数d满足 d <= sqrt(x), 考虑到sqrt每次都要去调用函数计算,因此可以s
package main import ( "bufio" "fmt" "os" "strconv" "strings" ) func main() { var reader = bufio.NewReader(os.Stdin) var n = readInt(reader) for i := 0; i < n; i++ { var num = readInt(reader) fmt.Println(okString(num)) } } func okString(num int) string { if ok(num) { return "Yes" } return "No" } func ok(num int) bool { if num <= 1 { return false } for i := 2; i < num/i+1; i++ { if num%i == 0 { return false } } return true } func readLine(reader *bufio.Reader) string { var line, _ = reader.ReadString('\n') return strings.TrimRight(line, "\n") } func readInt(reader *bufio.Reader) int { var a, _ = strconv.Atoi(readLine(reader)) return a } func readArray(reader *bufio.Reader, sep string) []int { var line = readLine(reader) var strList = strings.Split(line, sep) var nums = make([]int, 0) var err error var v int for i := 0; i < len(strList); i++ { if v, err = strconv.Atoi(strList[i]); err != nil { continue } nums = append(nums, v) } return nums }
分解质因数
试除法分解质因数 O(sqrt(n));O(logn) ~ O(sqrt(n))
package main import ( "bufio" "fmt" "os" "strconv" "strings" ) func main() { var reader = bufio.NewReader(os.Stdin) var n = readInt(reader) for i := 0; i < n; i++ { var num = readInt(reader) divide(num) } } func divide(num int) { for i := 2; i < num/i+1; i++ { if num%i != 0 { continue } var cnt int for num%i == 0 { num /= i cnt++ } fmt.Printf("%d %d\n", i, cnt) } if num > 1 { fmt.Printf("%d %d\n", num, 1) } fmt.Println() } func readLine(reader *bufio.Reader) string { var line, _ = reader.ReadString('\n') return strings.TrimRight(line, "\n") } func readInt(reader *bufio.Reader) int { var a, _ = strconv.Atoi(readLine(reader)) return a } func readArray(reader *bufio.Reader, sep string) []int { var line = readLine(reader) var strList = strings.Split(line, sep) var nums = make([]int, 0) var err error var v int for i := 0; i < len(strList); i++ { if v, err = strconv.Atoi(strList[i]); err != nil { continue } nums = append(nums, v) } return nums }
筛质数
朴素筛法
对于质数cnt++,对于每个数,将其倍数即为非质数
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
var nums = make([]*struct{}, 1000010)
var cnt int
var reader = bufio.NewReader(os.Stdin)
var n = readInt(reader)
for x := 2; x < n+1; x++ {
if nums[x] == nil {
cnt++
}
var t = 2 * x
for t <= n {
nums[t] = &struct{}{}
t += x
}
}
fmt.Println(cnt)
}
func readLine(reader *bufio.Reader) string {
var line, _ = reader.ReadString('\n')
return strings.TrimRight(line, "\n")
}
func readInt(reader *bufio.Reader) int {
var a, _ = strconv.Atoi(readLine(reader))
return a
}
func readArray(reader *bufio.Reader, sep string) []int {
var line = readLine(reader)
var strList = strings.Split(line, sep)
var nums = make([]int, 0)
var err error
var v int
for i := 0; i < len(strList); i++ {
if v, err = strconv.Atoi(strList[i]); err != nil {
continue
}
nums = append(nums, v)
}
return nums
}
埃氏筛法
由算术基本定理,只需要筛除质数的倍数元素即可。就是说对于非质数continue,对于质数那么则需要标记其倍数为非质数。
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
var nums = make([]*struct{}, 1000010)
var cnt int
var reader = bufio.NewReader(os.Stdin)
var n = readInt(reader)
for x := 2; x < n+1; x++ {
if nums[x] != nil {
continue
}
cnt++
var t = 2 * x
for t <= n {
nums[t] = &struct{}{}
t += x
}
}
fmt.Println(cnt)
}
func readLine(reader *bufio.Reader) string {
var line, _ = reader.ReadString('\n')
return strings.TrimRight(line, "\n")
}
func readInt(reader *bufio.Reader) int {
var a, _ = strconv.Atoi(readLine(reader))
return a
}
func readArray(reader *bufio.Reader, sep string) []int {
var line = readLine(reader)
var strList = strings.Split(line, sep)
var nums = make([]int, 0)
var err error
var v int
for i := 0; i < len(strList); i++ {
if v, err = strconv.Atoi(strList[i]); err != nil {
continue
}
nums = append(nums, v)
}
return nums
}
线性筛法
对于一个非质数只会被它的最小质因子筛掉
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
var nums = make([]*struct{}, 1000010)
var cnt int
var zs = make([]int, 1000010)
var reader = bufio.NewReader(os.Stdin)
var n = readInt(reader)
for x := 2; x < n+1; x++ {
if nums[x] == nil {
zs[cnt] = x
cnt++
}
// 枚举质因数
for t := 0; zs[t] <= n/x; t++ {
nums[zs[t]*x] = &struct{}{}
if x%zs[t] == 0 { // zs[t]一定是x的最小质因子,zs[t]一定是zs[t]*x的最小质因子
break
} // else { // zs[t]一定小于的所有质因子,zs[t]也一定是zs[t]*x的最小质因子
}
}
fmt.Println(cnt)
}
func readLine(reader *bufio.Reader) string {
var line, _ = reader.ReadString('\n')
return strings.TrimRight(line, "\n")
}
func readInt(reader *bufio.Reader) int {
var a, _ = strconv.Atoi(readLine(reader))
return a
}
func readArray(reader *bufio.Reader, sep string) []int {
var line = readLine(reader)
var strList = strings.Split(line, sep)
var nums = make([]int, 0)
var err error
var v int
for i := 0; i < len(strList); i++ {
if v, err = strconv.Atoi(strList[i]); err != nil {
continue
}
nums = append(nums, v)
}
return nums
}
什么是约数
一个数x的约数指的是可以被x整除的数
约数个数:对于一个数N=(p1^a1) * (p2^a2) * ... * (pk^ak)
,他的约数个数为(a1+1)*(a2+1)*...*(ak+1)
,它的各约数的和为(p1^0 + p1^1 + ... + p1^a1) + ... + (pk^0 + pk^1 + ... + pk^ak)
一个数的所有约数
试除法求一个数的约数
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
"strings"
)
func main() {
var reader = bufio.NewReader(os.Stdin)
var n = readInt(reader)
for i := 0; i < n; i++ {
var num = readInt(reader)
fmt.Println(nums2string(getAns(num), " "))
}
}
func getAns(num int) []int {
var ans []int
var i = 1
for ; i < num/i; i++ {
if num%i == 0 {
ans = append(ans, i)
ans = append(ans, num/i)
}
}
if num == i*i {
ans = append(ans, i)
}
sort.Ints(ans)
return ans
}
func readLine(reader *bufio.Reader) string {
var line, _ = reader.ReadString('\n')
return strings.TrimRight(line, "\n")
}
func readInt(reader *bufio.Reader) int {
var a, _ = strconv.Atoi(readLine(reader))
return a
}
func readArray(reader *bufio.Reader, sep string) []int {
var line = readLine(reader)
var strList = strings.Split(line, sep)
var nums = make([]int, 0)
var err error
var v int
for i := 0; i < len(strList); i++ {
if v, err = strconv.Atoi(strList[i]); err != nil {
continue
}
nums = append(nums, v)
}
return nums
}
func nums2string(x []int, sep string) string {
var b strings.Builder
for i := 0; i < len(x); i++ {
b.WriteString(strconv.Itoa(x[i]))
b.WriteString(sep)
}
return b.String()
}
最后更新于
这有帮助吗?