55 lines
1 KiB
Go
55 lines
1 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"math"
|
|
"rcu"
|
|
)
|
|
|
|
func cantorPair(x, y int) int {
|
|
if x < 0 || y < 0 {
|
|
log.Fatal("Arguments must be non-negative integers.")
|
|
}
|
|
return (x*x + 3*x + 2*x*y + y + y*y) / 2
|
|
}
|
|
|
|
func pi(n int) int {
|
|
if n < 2 {
|
|
return 0
|
|
}
|
|
if n == 2 {
|
|
return 1
|
|
}
|
|
primes := rcu.Primes(int(math.Sqrt(float64(n))))
|
|
a := len(primes)
|
|
memoPhi := make(map[int]int)
|
|
|
|
var phi func(x, a int) int // recursive closure
|
|
phi = func(x, a int) int {
|
|
if a < 1 {
|
|
return x
|
|
}
|
|
if a == 1 {
|
|
return x - (x >> 1)
|
|
}
|
|
pa := primes[a-1]
|
|
if x <= pa {
|
|
return 1
|
|
}
|
|
key := cantorPair(x, a)
|
|
if v, ok := memoPhi[key]; ok {
|
|
return v
|
|
}
|
|
memoPhi[key] = phi(x, a-1) - phi(x/pa, a-1)
|
|
return memoPhi[key]
|
|
}
|
|
|
|
return phi(n, a) + a - 1
|
|
}
|
|
|
|
func main() {
|
|
for i, n := 0, 1; i <= 9; i, n = i+1, n*10 {
|
|
fmt.Printf("10^%d %d\n", i, pi(n))
|
|
}
|
|
}
|