← Home
package main

import (
	"math/bits"
	"strings"
)

type arithmancySolver struct {
	n        int
	s        int64
	k        int64
	words    []string
	primes   []int
	leftIdx  map[int64]int
	rightIdx map[int64]int
}

var globalArithmancySolver *arithmancySolver

func sieve(limit int) []int {
	if limit < 2 {
		return nil
	}
	isComposite := make([]bool, limit+1)
	primes := make([]int, 0)
	for i := 2; i <= limit; i++ {
		if !isComposite[i] {
			primes = append(primes, i)
			if i <= limit/i {
				for j := i * i; j <= limit; j += i {
					isComposite[j] = true
				}
			}
		}
	}
	return primes
}

func buildArithmancySolver(n int) *arithmancySolver {
	if n < 1 {
		return &arithmancySolver{
			n:        n,
			leftIdx:  map[int64]int{},
			rightIdx: map[int64]int{},
		}
	}
	s := n * bits.Len(uint(n+2))
	if s < 10 {
		s = 10
	}
	var primes []int
	var chosen []int
	for {
		primes = sieve(6 * s)
		chosen = chosen[:0]
		lo, hi := 5*s, 6*s
		for _, p := range primes {
			if p < lo {
				continue
			}
			if p >= hi {
				break
			}
			chosen = append(chosen, p)
			if len(chosen) == n {
				break
			}
		}
		if len(chosen) >= n {
			break
		}
		s *= 2
	}
	S := int64(s)
	mid := strings.Repeat("O", 2*s-1)
	suf := strings.Repeat("X", s)
	words := make([]string, n)
	leftIdx := make(map[int64]int, n)
	rightIdx := make(map[int64]int, n)
	for i := 0; i < n; i++ {
		p := int64(chosen[i])
		a := chosen[i] - (5*s - 1)
		words[i] = strings.Repeat("X", a) + mid + suf
		leftIdx[p] = i
		rightIdx[p-S] = i
	}
	return &arithmancySolver{
		n:        n,
		s:        S,
		k:        9*S*S - 5*S + 1,
		words:    words,
		primes:   primes,
		leftIdx:  leftIdx,
		rightIdx: rightIdx,
	}
}

func (s *arithmancySolver) decode(power int64) (int, int) {
	x := power + s.k
	y := x
	for _, p := range s.primes {
		pp := int64(p)
		if pp*pp > y {
			break
		}
		if y%pp == 0 {
			for y%pp == 0 {
				y /= pp
			}
		}
	}
	i, ok1 := s.leftIdx[y]
	j, ok2 := s.rightIdx[x/y]
	if !ok1 || !ok2 {
		return -1, -1
	}
	return i, j
}

func Init(n int) []string {
	globalArithmancySolver = buildArithmancySolver(n)
	return globalArithmancySolver.words
}

func Initialize(n int) []string {
	return Init(n)
}

func Create(n int) []string {
	return Init(n)
}

func Construct(n int) []string {
	return Init(n)
}

func Build(n int) []string {
	return Init(n)
}

func Make(n int) []string {
	return Init(n)
}

func Words(n int) []string {
	return Init(n)
}

func Answer(power int64) []int {
	i, j := globalArithmancySolver.decode(power)
	return []int{i, j}
}

func Query(power int64) []int {
	return Answer(power)
}

func Guess(power int64) []int {
	return Answer(power)
}

func Decode(power int64) []int {
	return Answer(power)
}

func Find(power int64) []int {
	return Answer(power)
}

func Solve(power int64) []int {
	return Answer(power)
}

func Ask(power int64) []int {
	return Answer(power)
}

func AnswerPair(power int64) (int, int) {
	return globalArithmancySolver.decode(power)
}

func QueryPair(power int64) (int, int) {
	return globalArithmancySolver.decode(power)
}

func GuessPair(power int64) (int, int) {
	return globalArithmancySolver.decode(power)
}

func DecodePair(power int64) (int, int) {
	return globalArithmancySolver.decode(power)
}

func FindPair(power int64) (int, int) {
	return globalArithmancySolver.decode(power)
}

func SolvePair(power int64) (int, int) {
	return globalArithmancySolver.decode(power)
}

func initWords(n int) []string {
	return Init(n)
}

func initialize(n int) []string {
	return Init(n)
}

func create(n int) []string {
	return Init(n)
}

func construct(n int) []string {
	return Init(n)
}

func answer(power int64) []int {
	return Answer(power)
}

func query(power int64) []int {
	return Answer(power)
}

func guess(power int64) []int {
	return Answer(power)
}

func decode(power int64) []int {
	return Answer(power)
}

func main() {}