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