push
This commit is contained in:
commit
e09e88e69c
7 changed files with 2333 additions and 0 deletions
192
bigints.nim
Normal file
192
bigints.nim
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
import strutils
|
||||
|
||||
const BASE = 1_000_000_000'u64
|
||||
const BASE_DIGITS = 9
|
||||
|
||||
type
|
||||
BigInt* = object
|
||||
sign*: int # -1, 0, 1
|
||||
digits*: seq[uint32] # little endian limbs
|
||||
|
||||
|
||||
proc normalize(a: var BigInt) =
|
||||
while a.digits.len > 0 and a.digits[^1] == 0:
|
||||
a.digits.setLen(a.digits.len - 1)
|
||||
|
||||
if a.digits.len == 0:
|
||||
a.sign = 0
|
||||
elif a.sign == 0:
|
||||
a.sign = 1
|
||||
|
||||
|
||||
proc big*(x: int): BigInt =
|
||||
if x == 0:
|
||||
return BigInt(sign: 0)
|
||||
|
||||
var v = abs(x)
|
||||
result.sign = if x < 0: -1 else: 1
|
||||
|
||||
while v > 0:
|
||||
result.digits.add(uint32(v mod int(BASE)))
|
||||
v = v div int(BASE)
|
||||
|
||||
|
||||
proc parse*(s: string): BigInt =
|
||||
var str = s
|
||||
result.sign = 1
|
||||
|
||||
if str[0] == '-':
|
||||
result.sign = -1
|
||||
str = str[1..^1]
|
||||
|
||||
for i in countdown(str.len, 1, BASE_DIGITS):
|
||||
let start = max(0, i - BASE_DIGITS)
|
||||
let chunk = parseInt(str[start..<i])
|
||||
result.digits.add(uint32(chunk))
|
||||
|
||||
result.normalize()
|
||||
|
||||
|
||||
proc cmp(a, b: BigInt): int =
|
||||
if a.digits.len != b.digits.len:
|
||||
return cmp(a.digits.len, b.digits.len)
|
||||
|
||||
for i in countdown(a.digits.len - 1, 0):
|
||||
if a.digits[i] != b.digits[i]:
|
||||
return cmp(a.digits[i], b.digits[i])
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
proc `==`*(a, b: BigInt): bool =
|
||||
a.sign == b.sign and a.digits == b.digits
|
||||
|
||||
|
||||
proc add(a, b: BigInt): BigInt =
|
||||
var carry: uint64 = 0
|
||||
let n = max(a.digits.len, b.digits.len)
|
||||
|
||||
result.digits = newSeq[uint32](n)
|
||||
|
||||
for i in 0..<n:
|
||||
var x = carry
|
||||
|
||||
if i < a.digits.len: x += a.digits[i]
|
||||
if i < b.digits.len: x += b.digits[i]
|
||||
|
||||
result.digits[i] = uint32(x mod BASE)
|
||||
carry = x div BASE
|
||||
|
||||
if carry > 0:
|
||||
result.digits.add(uint32(carry))
|
||||
|
||||
result.sign = 1
|
||||
result.normalize()
|
||||
|
||||
|
||||
proc sub(a, b: BigInt): BigInt =
|
||||
var borrow: int64 = 0
|
||||
result.digits = newSeq[uint32](a.digits.len)
|
||||
|
||||
for i in 0..<a.digits.len:
|
||||
var x = int64(a.digits[i]) - borrow
|
||||
if i < b.digits.len:
|
||||
x -= int64(b.digits[i])
|
||||
|
||||
if x < 0:
|
||||
x += int64(BASE)
|
||||
borrow = 1
|
||||
else:
|
||||
borrow = 0
|
||||
|
||||
result.digits[i] = uint32(x)
|
||||
|
||||
result.sign = 1
|
||||
result.normalize()
|
||||
|
||||
|
||||
proc `+`*(a, b: BigInt): BigInt =
|
||||
if a.sign == 0: return b
|
||||
if b.sign == 0: return a
|
||||
|
||||
if a.sign == b.sign:
|
||||
result = add(a, b)
|
||||
result.sign = a.sign
|
||||
else:
|
||||
let c = cmp(a, b)
|
||||
|
||||
if c == 0:
|
||||
return BigInt(sign: 0)
|
||||
|
||||
if c > 0:
|
||||
result = sub(a, b)
|
||||
result.sign = a.sign
|
||||
else:
|
||||
result = sub(b, a)
|
||||
result.sign = b.sign
|
||||
|
||||
|
||||
proc `-`*(a, b: BigInt): BigInt =
|
||||
var nb = b
|
||||
nb.sign *= -1
|
||||
a + nb
|
||||
|
||||
|
||||
proc `*`*(a, b: BigInt): BigInt =
|
||||
if a.sign == 0 or b.sign == 0:
|
||||
return BigInt(sign: 0)
|
||||
|
||||
result.digits = newSeq[uint32](a.digits.len + b.digits.len)
|
||||
|
||||
for i in 0..<a.digits.len:
|
||||
var carry: uint64 = 0
|
||||
|
||||
for j in 0..<b.digits.len:
|
||||
let k = i + j
|
||||
|
||||
var cur =
|
||||
uint64(result.digits[k]) +
|
||||
uint64(a.digits[i]) * uint64(b.digits[j]) +
|
||||
carry
|
||||
|
||||
result.digits[k] = uint32(cur mod BASE)
|
||||
carry = cur div BASE
|
||||
|
||||
var pos = i + b.digits.len
|
||||
|
||||
while carry > 0:
|
||||
let cur = uint64(result.digits[pos]) + carry
|
||||
result.digits[pos] = uint32(cur mod BASE)
|
||||
carry = cur div BASE
|
||||
inc pos
|
||||
|
||||
result.sign = a.sign * b.sign
|
||||
result.normalize()
|
||||
|
||||
|
||||
proc `$`*(a: BigInt): string =
|
||||
if a.sign == 0:
|
||||
return "0"
|
||||
|
||||
var parts: seq[string]
|
||||
|
||||
for d in a.digits:
|
||||
parts.add($d)
|
||||
|
||||
result = parts[^1]
|
||||
|
||||
for i in countdown(parts.len - 2, 0):
|
||||
result.add(parts[i].align(BASE_DIGITS, '0'))
|
||||
|
||||
if a.sign < 0:
|
||||
result = "-" & result
|
||||
|
||||
|
||||
when isMainModule:
|
||||
let a = parse("123456789123456789123456789")
|
||||
let b = parse("987654321987654321987654321")
|
||||
|
||||
echo "a = ", a
|
||||
echo "b = ", b
|
||||
echo "a + b = ", a + b
|
||||
echo "a * b = ", a * b
|
||||
112
fenwick.nim
Normal file
112
fenwick.nim
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
type Fenwick*[T] = ref object
|
||||
arr*: seq[T]
|
||||
|
||||
type FenwickMod*[T] = ref object
|
||||
arr*: seq[T]
|
||||
m*: int64
|
||||
|
||||
proc Fenwick*[T](f: var Fenwick[T], len: int): void =
|
||||
new(f)
|
||||
f.arr.newSeq(len)
|
||||
|
||||
proc Fenwick*[T](f: var Fenwick[T], len: int, default: T): void =
|
||||
##ializes a fenwick tree with a constant array, f[i] = default for all i.
|
||||
new(f)
|
||||
f.arr.newSeq(len)
|
||||
for i in 0..<len:
|
||||
f.arr[i] = default
|
||||
for i in 1..len:
|
||||
var j = i + (i and (-i))
|
||||
if j<=len: f.arr[j-1] += f.arr[i-1]
|
||||
|
||||
proc Fenwick*[T](f: var Fenwick[T], default: seq[T]): void =
|
||||
##Converts the seq into a fenwick tree in O(default.len) time.
|
||||
new(f)
|
||||
f.arr = default
|
||||
for i in 1..default.len:
|
||||
var j = i + (i and (-i))
|
||||
if j<=default.len: f.arr[j-1] += f.arr[i-1]
|
||||
|
||||
proc Fenwick*[T](f: var FenwickMod[T], len: int, m: int64): void =
|
||||
new(f)
|
||||
f.arr.newSeq(len)
|
||||
f.m = m
|
||||
|
||||
proc Fenwick*[T](f: var FenwickMod[T], len: int, default: T): void =
|
||||
##ializes a fenwick tree with a constant array, f[i] = default for all i.
|
||||
new(f)
|
||||
f.arr.newSeq(len)
|
||||
for i in 0..<len:
|
||||
f.arr[i] = default
|
||||
for i in 1..len:
|
||||
var j = i + (i and (-i))
|
||||
if j<=len: f.arr[j-1] = (f.arr[j-1] + f.arr[i-1]) mod f.m
|
||||
|
||||
proc Fenwick*[T](f: var FenwickMod[T], default: seq[T]): void =
|
||||
##Converts the seq into a fenwick tree in O(default.len) time.
|
||||
new(f)
|
||||
f.arr = default
|
||||
for i in 1..len:
|
||||
var j = i + (i and (-i))
|
||||
if j<=len: f.arr[j-1] = (f.arr[j-1] + f.arr[i-1]) mod f.m
|
||||
|
||||
type SomeFenwick*[T] = Fenwick[T] | FenwickMod[T]
|
||||
|
||||
|
||||
proc len*[T](f: SomeFenwick[T]): int = f.arr.len
|
||||
|
||||
proc sum*[T](f: Fenwick[T], i: SomeInteger): T =
|
||||
##Returns f[0] + f[1] + ... + f[i]. Time O(log i).
|
||||
var ii = i+1
|
||||
while ii>0:
|
||||
result += f.arr[ii-1]
|
||||
ii -= (ii and (-ii))
|
||||
|
||||
proc sum*[T](f: FenwickMod[T], i: SomeInteger): int64 =
|
||||
##Returns f[0] + f[1] + ... + f[i]. Time O(log i).
|
||||
var ii = i+1
|
||||
while ii>0:
|
||||
result += f.arr[ii-1]
|
||||
result = result mod f.m
|
||||
ii -= (ii and (-ii))
|
||||
|
||||
proc addTo*[T](f: Fenwick[T], i: SomeInteger, x: T): void =
|
||||
var ii = i+1
|
||||
while ii<=f.arr.len:
|
||||
f.arr[ii-1] += x
|
||||
ii += (ii and (-ii))
|
||||
|
||||
proc addTo*[T](f: var Fenwick[T], vals: seq[T]): void =
|
||||
##Adds vals[i] to f[i] for each i. Time O(vals.len).
|
||||
var vals = vals
|
||||
for i in 1..vals.len:
|
||||
var j = i + (i and (-i))
|
||||
if j<=vals.len: vals[j-1] = vals[j-1] + vals[i-1]
|
||||
f.arr[i-1] += vals[i-1]
|
||||
|
||||
proc addTo*[T](f: FenwickMod[T], i: SomeInteger, x: T): void =
|
||||
var ii = i+1
|
||||
while ii<=f.arr.len:
|
||||
f.arr[ii-1] += x
|
||||
f.arr[ii-1] = (f.arr[ii-1] mod f.m).T
|
||||
ii += (ii and (-ii))
|
||||
|
||||
proc addTo*[T](f: var FenwickMod[T], vals: seq[T]): void =
|
||||
##Adds vals[i] to f[i] for each i. Time O(vals.len).
|
||||
var vals = vals
|
||||
for i in 1..vals.len:
|
||||
var j = i + (i and (-i))
|
||||
if j<=vals.len: vals[j-1] = (vals[j-1] + vals[i-1]) mod f.m
|
||||
f.arr[i-1] = (f.arr[i-1] + vals[i-1]) mod f.m
|
||||
|
||||
proc `[]`*[T](f: Fenwick[T], i: SomeInteger): T =
|
||||
if i==0: return f.sum(0)
|
||||
return f.sum(i) - f.sum(i-1)
|
||||
|
||||
proc `[]`*[T](f: FenwickMod[T], i: SomeInteger): T =
|
||||
##Accesses a single element of the base array. O(log i)
|
||||
if i==0: return f.sum(0)
|
||||
return (f.sum(i) - f.sum(i-1) + f.m) mod f.m
|
||||
|
||||
proc `[]=`*[T](f: SomeFenwick[T], i: SomeInteger, x: T): void =
|
||||
f.addTo(i, x-f[i])
|
||||
1484
graphs.nim
Normal file
1484
graphs.nim
Normal file
File diff suppressed because it is too large
Load diff
152
nt.nim
Normal file
152
nt.nim
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
import std/[sequtils]
|
||||
|
||||
const MOD* = 1000000007
|
||||
type ll* = int64
|
||||
|
||||
proc reduce*(x: ll): ll =
|
||||
var r = x mod MOD
|
||||
if r < 0: r += MOD
|
||||
r
|
||||
|
||||
proc bexp*(b: ll, p: ll): ll =
|
||||
var
|
||||
curr = reduce(b)
|
||||
power = p
|
||||
res: ll = 1
|
||||
while power > 0:
|
||||
if (power and 1) == 1:
|
||||
res = (res * curr) mod MOD
|
||||
curr = (curr * curr) mod MOD
|
||||
power = power shr 1
|
||||
res
|
||||
|
||||
proc inv*(x: ll): ll =
|
||||
bexp(x, MOD - 2)
|
||||
|
||||
type
|
||||
Combinatorics*[N: static[int]] = object
|
||||
factorialCache: array[N+1, ll]
|
||||
inverseFactorialCache: array[N+1, ll]
|
||||
|
||||
proc initCombinatorics*[N: static[int]](): Combinatorics[N] =
|
||||
var c: Combinatorics[N]
|
||||
c.factorialCache[0] = 1
|
||||
|
||||
for i in 1..N:
|
||||
c.factorialCache[i] = (c.factorialCache[i-1] * i) mod MOD
|
||||
|
||||
c.inverseFactorialCache[N] = inv(c.factorialCache[N])
|
||||
|
||||
for i in countdown(N-1, 0):
|
||||
c.inverseFactorialCache[i] =
|
||||
((i+1).ll * c.inverseFactorialCache[i+1]) mod MOD
|
||||
|
||||
c
|
||||
|
||||
proc fact*[N](c: Combinatorics[N], x: int): ll =
|
||||
c.factorialCache[x]
|
||||
|
||||
proc ifact*[N](c: Combinatorics[N], x: int): ll =
|
||||
c.inverseFactorialCache[x]
|
||||
|
||||
proc permute*[N](c: Combinatorics[N], n, k: int): ll =
|
||||
if k > n: return 0
|
||||
(c.fact(n) * c.ifact(n-k)) mod MOD
|
||||
|
||||
proc choose*[N](c: Combinatorics[N], n, k: int): ll =
|
||||
if k > n: return 0
|
||||
(((c.fact(n) * c.ifact(k)) mod MOD) * c.ifact(n-k)) mod MOD
|
||||
|
||||
proc gcd*(a, b: ll): ll =
|
||||
if b == 0: a else: gcd(b, a mod b)
|
||||
|
||||
proc lcm*(a, b: ll): ll =
|
||||
(a div gcd(a,b)) * b
|
||||
|
||||
type
|
||||
EGCDResult* = object
|
||||
x*: ll
|
||||
y*: ll
|
||||
d*: ll
|
||||
|
||||
proc extendedGcd*(a, b: ll): EGCDResult =
|
||||
if b == 0:
|
||||
return EGCDResult(x: 1, y: 0, d: a)
|
||||
|
||||
let next = extendedGcd(b, a mod b)
|
||||
|
||||
EGCDResult(
|
||||
x: next.y,
|
||||
y: next.x - (a div b) * next.y,
|
||||
d: next.d
|
||||
)
|
||||
|
||||
type
|
||||
FactorSieve*[N: static[int]] = object
|
||||
sieve: array[N+1, int]
|
||||
|
||||
proc initFactorSieve*[N: static[int]](): FactorSieve[N] =
|
||||
var s: FactorSieve[N]
|
||||
s.sieve[1] = 1
|
||||
|
||||
for i in 2..N:
|
||||
if s.sieve[i] == 0:
|
||||
for j in countup(i, N, i):
|
||||
s.sieve[j] = i
|
||||
|
||||
s
|
||||
|
||||
proc factor*[N](s: FactorSieve[N], x0: int): seq[(int,int)] =
|
||||
var x = x0
|
||||
var res: seq[(int,int)] = @[]
|
||||
|
||||
while x != 1:
|
||||
let curr = s.sieve[x]
|
||||
var cnt = 0
|
||||
|
||||
while s.sieve[x] == curr:
|
||||
inc cnt
|
||||
x = x div curr
|
||||
|
||||
res.add((curr,cnt))
|
||||
|
||||
res
|
||||
|
||||
type
|
||||
BooleanSieve*[N: static[int]] = object
|
||||
isComposite: array[N+1, bool]
|
||||
|
||||
proc initBooleanSieve*[N: static[int]](): BooleanSieve[N] =
|
||||
var s: BooleanSieve[N]
|
||||
s.isComposite[1] = true
|
||||
|
||||
for i in 2..N:
|
||||
if not s.isComposite[i]:
|
||||
for j in countup(2*i, N, i):
|
||||
s.isComposite[j] = true
|
||||
|
||||
s
|
||||
|
||||
proc isPrime*[N](s: BooleanSieve[N], x: int): bool =
|
||||
not s.isComposite[x]
|
||||
|
||||
# ---------------- MAIN ----------------
|
||||
|
||||
proc main() =
|
||||
let comb = initCombinatorics[100000]()
|
||||
echo "10 choose 3 = ", comb.choose(10,3)
|
||||
|
||||
echo "gcd(48,18) = ", gcd(48,18)
|
||||
echo "lcm(48,18) = ", lcm(48,18)
|
||||
|
||||
let eg = extendedGcd(48,18)
|
||||
echo "extended gcd: x=", eg.x, " y=", eg.y, " d=", eg.d
|
||||
|
||||
let sieve = initFactorSieve[100000]()
|
||||
echo "Factors of 84: ", sieve.factor(84)
|
||||
|
||||
let bs = initBooleanSieve[100000]()
|
||||
echo "Is 97 prime? ", bs.isPrime(97)
|
||||
|
||||
when isMainModule:
|
||||
main()
|
||||
45
segmented.nim
Normal file
45
segmented.nim
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import math, sequtils
|
||||
proc simple(limit: int): seq[int] =
|
||||
var isPrime = newSeq[bool](limit + 1)
|
||||
for i in 0..limit:
|
||||
isPrime[i] = true
|
||||
isPrime[0] = false
|
||||
isPrime[1] = false
|
||||
|
||||
for i in 2..int(sqrt(float(limit))):
|
||||
if isPrime[i]:
|
||||
var j = i * i
|
||||
while j <= limit:
|
||||
isPrime[j] = false
|
||||
j += i
|
||||
|
||||
result = @[]
|
||||
for i, prime in isPrime:
|
||||
if prime:
|
||||
result.add(i)
|
||||
|
||||
proc segmented(L, R: int): seq[int] =
|
||||
let limit = int(sqrt(float(R)))
|
||||
let primes = simple(limit)
|
||||
var isPrime = newSeq[bool](R - L + 1)
|
||||
for i in 0..<isPrime.len:
|
||||
isPrime[i] = true
|
||||
|
||||
for p in primes:
|
||||
var start = (L div p) * p
|
||||
if start < L: start += p
|
||||
if start == p: start += p
|
||||
|
||||
var j = start
|
||||
while j <= R:
|
||||
isPrime[j - L] = false
|
||||
j += p
|
||||
|
||||
result = @[]
|
||||
for i in 0..<isPrime.len:
|
||||
if isPrime[i] and (i + L >= 2):
|
||||
result.add(i + L)
|
||||
|
||||
let L = 10
|
||||
let R = 500000000
|
||||
echo segmented(L, R)
|
||||
98
segtree.nim
Normal file
98
segtree.nim
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
type SegTree*[T, U] = ref object
|
||||
len*: int
|
||||
arr*: seq[T]
|
||||
shift*: seq[U]
|
||||
|
||||
proc SegTree*[T, U](f: var SegTree[T, U], len: int): void =
|
||||
new(f)
|
||||
f.len = len
|
||||
f.arr.newSeq(4*len)
|
||||
f.shift.newSeq(4*len)
|
||||
|
||||
proc build[T, U](f: var SegTree[T, U], v, tl, tr: int, a: seq[T]): void =
|
||||
if tl==tr:
|
||||
f.arr[v] = a[tl]
|
||||
else:
|
||||
var tm: int = (tl + tr) div 2
|
||||
f.build(2*v, tl, tm, a)
|
||||
f.build(2*v+1, tm+1, tr, a)
|
||||
f.arr[v] = f.arr[2*v] + f.arr[2*v+1]
|
||||
|
||||
proc build*[T, U](f: var SegTree[T, U], a: seq[T]): void =
|
||||
f.build(1, 0, f.len - 1, a)
|
||||
|
||||
proc modifyRange[T, U](tl, tr: int, sum: T, x: U, additive: bool): T =
|
||||
if additive: return sum @ ((tr-tl+1) * x)
|
||||
else: return sum @ x
|
||||
|
||||
proc sum[T, U, R](f: var SegTree[T, U], v, tl, tr, l, r: int, phi: proc (x: T): R, additive: bool): R =
|
||||
if l>r:
|
||||
return
|
||||
if f.shift[v] - f.shift[v] != f.shift[v]: #nonzero
|
||||
f.arr[v] = modifyRange(tl, tr, f.arr[v], f.shift[v], additive)
|
||||
if tl!=tr:
|
||||
f.shift[2*v] = f.shift[2*v] + f.shift[v]
|
||||
f.shift[2*v+1] = f.shift[2*v+1] + f.shift[v]
|
||||
f.shift[v] = f.shift[v] - f.shift[v]
|
||||
if l<=tl and tr<=r: return f.arr[v].phi
|
||||
elif tl!=tr:
|
||||
var tm: int = (tl + tr) div 2
|
||||
return f.sum(2*v, tl, tm, l, min(r, tm), phi, additive) + f.sum(2*v+1, tm+1, tr, max(l, tm+1), r, phi, additive)
|
||||
|
||||
proc sum*[T, U, R](f: var SegTree[T, U], i, j: int, phi: proc (x: T): R, additive: bool): R =
|
||||
return f.sum(1, 0, f.len - 1, i, j, phi, additive)
|
||||
|
||||
proc showDetails*[T, U](f: var SegTree[T, U], v: int = 1, tl: int = 0, tr: int = f.len - 1, prefix: string = ""): void =
|
||||
echo prefix, "(", tl, ", ", tr, "): ", f.arr[v], ", ", f.shift[v]
|
||||
if tl != tr:
|
||||
var tm: int = (tl + tr) div 2
|
||||
f.showDetails(2*v, tl, tm, prefix & " ")
|
||||
f.showDetails(2*v+1, tm+1, tr, prefix & " ")
|
||||
|
||||
|
||||
proc applyTo[T, U](f: var SegTree[T, U], v, tl, tr, l, r: int, x: U, additive: bool): void =
|
||||
if f.shift[v] - f.shift[v] != f.shift[v]: #nonzero
|
||||
f.arr[v] = modifyRange(tl, tr, f.arr[v], f.shift[v], additive)
|
||||
if tl != tr:
|
||||
f.shift[2*v] = f.shift[2*v] + f.shift[v]
|
||||
f.shift[2*v+1] = f.shift[2*v+1] + f.shift[v]
|
||||
f.shift[v] = f.shift[v] - f.shift[v]
|
||||
if tl>tr or tl>r or tr<l: return
|
||||
if l<=tl and tr<=r:
|
||||
f.arr[v] = modifyRange(tl, tr, f.arr[v], x, additive)
|
||||
if tl != tr:
|
||||
f.shift[2*v] = f.shift[2*v] + x
|
||||
f.shift[2*v+1] = f.shift[2*v+1] + x
|
||||
elif tl!=tr:
|
||||
var tm: int = (tl + tr) div 2
|
||||
f.applyTo(2*v, tl, tm, l, min(r, tm), x, additive)
|
||||
f.applyTo(2*v+1, tm+1, tr, max(l, tm+1), r, x, additive)
|
||||
f.arr[v] = f.arr[2*v] + f.arr[2*v+1]
|
||||
|
||||
proc addTo*[T, U](f: var SegTree[T, U], i, j: int, x: U): void =
|
||||
|
||||
f.applyTo(1, 0, f.len - 1, i, j, x, true)
|
||||
|
||||
proc multTo*[T, U](f: var SegTree[T, U], i, j: int, x: U): void =
|
||||
|
||||
f.applyTo(1, 0, f.len - 1, i, j, x, false)
|
||||
|
||||
proc toBaseArray*[T, U, R](f: var SegTree[T, U], phi: proc (x: T): R, additive: bool): seq[R] =
|
||||
result.newSeq(f.len)
|
||||
for i in 0..<f.len:
|
||||
result[i] = f.sum(i, i, phi, additive)
|
||||
|
||||
when isMainModule:
|
||||
proc `@`(x, y: int): int = x + y
|
||||
var seg: SegTree[int, int]
|
||||
seg.SegTree(10)
|
||||
var a: seq[int] = @[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
seg.build(a)
|
||||
seg.showDetails
|
||||
proc phi(x: int): int = x
|
||||
seg.addTo(1, 8, 4)
|
||||
seg.showDetails
|
||||
seg.addTo(3, 9, 4)
|
||||
seg.showDetails
|
||||
for i in 0..9:
|
||||
echo i, ": ", seg.sum(i, i, phi, true)
|
||||
250
sieve.nim
Normal file
250
sieve.nim
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
import math
|
||||
|
||||
type
|
||||
Factor* = object
|
||||
prime*: uint64
|
||||
power*: uint64
|
||||
|
||||
Factors* = object
|
||||
numPrimes*: uint64
|
||||
factors*: seq[Factor]
|
||||
|
||||
U64Array* = object
|
||||
elems*: seq[uint64]
|
||||
|
||||
# =========================
|
||||
# Utilities
|
||||
# =========================
|
||||
|
||||
proc factorAppend*(f: var Factors, p, k: uint64) =
|
||||
f.factors.add Factor(prime: p, power: k)
|
||||
inc f.numPrimes
|
||||
|
||||
# =========================
|
||||
# Math helpers
|
||||
# =========================
|
||||
|
||||
proc u64Pow*(a, e: uint64): uint64 =
|
||||
var base = a
|
||||
var exp = e
|
||||
var r: uint64 = 1
|
||||
while exp > 0:
|
||||
if (exp and 1) == 1:
|
||||
r *= base
|
||||
base *= base
|
||||
exp = exp shr 1
|
||||
r
|
||||
|
||||
proc u64NthRoot*(x, n: uint64): uint64 =
|
||||
uint64(pow(float64(x), 1.0 / float64(n)))
|
||||
|
||||
proc u64Binom*(n, k: uint64): uint64 =
|
||||
if k > n: return 0
|
||||
var r: uint64 = 1
|
||||
for i in 1..k:
|
||||
r = r * (n - k + i) div i
|
||||
r
|
||||
|
||||
proc i64Gcd*(a, b: int64): int64 =
|
||||
var x = a
|
||||
var y = b
|
||||
while y != 0:
|
||||
let t = x mod y
|
||||
x = y
|
||||
y = t
|
||||
x
|
||||
|
||||
proc i64Lcm*(a, b: int64): int64 =
|
||||
(a div i64Gcd(a, b)) * b
|
||||
|
||||
proc i64Egcd*(a, b: int64, x, y: var int64): int64 =
|
||||
if b == 0:
|
||||
x = 1
|
||||
y = 0
|
||||
return a
|
||||
|
||||
var x1, y1: int64
|
||||
let g = i64Egcd(b, a mod b, x1, y1)
|
||||
x = y1
|
||||
y = x1 - y1 * (a div b)
|
||||
g
|
||||
|
||||
# =========================
|
||||
# Prime estimate helpers
|
||||
# =========================
|
||||
|
||||
proc maxPrimeDivs*(max: uint64): uint64 =
|
||||
let primorials = [
|
||||
6'u64,30,210,2310,30030,
|
||||
510510,9699690,223092870
|
||||
]
|
||||
|
||||
for i, p in primorials:
|
||||
if max < p:
|
||||
return uint64(i+1)
|
||||
|
||||
15
|
||||
|
||||
proc maxPrimesLe*(max: uint64): uint64 =
|
||||
uint64(1.25506 * float64(max) / ln(float64(max)))
|
||||
|
||||
# =========================
|
||||
# Omega sieve
|
||||
# =========================
|
||||
|
||||
proc sieveOmega*(max: uint64): seq[uint8] =
|
||||
result = newSeq[uint8](max+1)
|
||||
|
||||
for n in 2..max:
|
||||
if result[n] != 0: continue
|
||||
var m = n
|
||||
while m <= max:
|
||||
inc result[m]
|
||||
m += n
|
||||
|
||||
# =========================
|
||||
# Largest prime factor sieve
|
||||
# =========================
|
||||
|
||||
proc sieveLargestFactors*(max: uint64): seq[uint64] =
|
||||
result = newSeq[uint64](max+1)
|
||||
|
||||
for p in 2..max:
|
||||
if result[p] != 0: continue
|
||||
var m = p
|
||||
while m <= max:
|
||||
result[m] = p
|
||||
m += p
|
||||
|
||||
# =========================
|
||||
# Smallest prime factor sieve
|
||||
# =========================
|
||||
|
||||
proc sieveSmallestFactors*(max: uint64): seq[uint32] =
|
||||
result = newSeq[uint32](max+1)
|
||||
|
||||
let r = uint64(sqrt(float64(max)))
|
||||
|
||||
for p in 2..r:
|
||||
if result[p] != 0: continue
|
||||
|
||||
var m = p*p
|
||||
while m <= max:
|
||||
if result[m] == 0:
|
||||
result[m] = uint32(p)
|
||||
m += p
|
||||
|
||||
for i in 2..max:
|
||||
if result[i] == 0:
|
||||
result[i] = uint32(i)
|
||||
|
||||
# =========================
|
||||
# Factorization
|
||||
# =========================
|
||||
|
||||
proc fillFactorsFromSmallest*(res: var Factors, n: uint64, spf: seq[uint32]) =
|
||||
var x = n
|
||||
res.numPrimes = 0
|
||||
res.factors.setLen(0)
|
||||
|
||||
while x > 1:
|
||||
let p = uint64(spf[x])
|
||||
var k: uint64 = 0
|
||||
|
||||
while spf[x] == uint32(p):
|
||||
x = x div p
|
||||
inc k
|
||||
|
||||
factorAppend(res, p, k)
|
||||
# =========================
|
||||
# Totient sieve
|
||||
# =========================
|
||||
|
||||
proc sievePhi*(max: uint64): seq[uint64] =
|
||||
result = newSeq[uint64](max+1)
|
||||
|
||||
for i in 1..max:
|
||||
result[i] = i
|
||||
|
||||
for p in 2..max:
|
||||
if result[p] != p: continue
|
||||
|
||||
var m = p
|
||||
while m <= max:
|
||||
result[m] -= result[m] div p
|
||||
m += p
|
||||
|
||||
# =========================
|
||||
# Sigma_0 (divisor count)
|
||||
# =========================
|
||||
|
||||
proc sigma0*(max: uint64): seq[uint64] =
|
||||
result = newSeq[uint64](max+1)
|
||||
|
||||
for i in 1..max:
|
||||
var j = i
|
||||
while j <= max:
|
||||
inc result[j]
|
||||
j += i
|
||||
|
||||
# =========================
|
||||
# Mobius sieve
|
||||
# =========================
|
||||
|
||||
proc mobius*(max: uint64): seq[int8] =
|
||||
result = newSeq[int8](max+1)
|
||||
|
||||
for i in 1..max:
|
||||
result[i] = 1
|
||||
|
||||
for p in 2..max:
|
||||
if result[p] == 1:
|
||||
var m = p
|
||||
while m <= max:
|
||||
result[m] = -result[m]
|
||||
m += p
|
||||
|
||||
let p2 = p*p
|
||||
m = p2
|
||||
while m <= max:
|
||||
result[m] = 0
|
||||
m += p2
|
||||
|
||||
# =========================
|
||||
# Prime sieve
|
||||
# =========================
|
||||
|
||||
proc sievePrimes*(max: uint64): seq[uint64] =
|
||||
var isComp = newSeq[bool](max+1)
|
||||
|
||||
for p in 2..max:
|
||||
if isComp[p]: continue
|
||||
|
||||
result.add p
|
||||
|
||||
if p*p <= max:
|
||||
var m = p*p
|
||||
while m <= max:
|
||||
isComp[m] = true
|
||||
m += p
|
||||
|
||||
# =========================
|
||||
# Main
|
||||
# =========================
|
||||
|
||||
when isMainModule:
|
||||
|
||||
let max = 10_000_000'u64
|
||||
|
||||
let primes = sievePrimes(max)
|
||||
|
||||
echo "Primes up to ", max, ":"
|
||||
for p in primes:
|
||||
stdout.write($p & " ")
|
||||
echo ""
|
||||
|
||||
let phi = sievePhi(max)
|
||||
echo "phi(36) = ", phi[36]
|
||||
|
||||
let mu = mobius(max)
|
||||
echo "mu(30) = ", mu[30]
|
||||
Loading…
Add table
Add a link
Reference in a new issue