Skip to main content

prime_factors

Function prime_factors 

Source
pub fn prime_factors(n: u64) -> Vec<(u64, u32)>
Examples found in repository?
crates/competitive/src/math/arbitrary_mod_binomial.rs (line 215)
213    pub fn new(modulus: u64, max_n: u64) -> Self {
214        assert_ne!(modulus, 0);
215        let ppbs = prime_factors(modulus)
216            .into_iter()
217            .map(|(p, e)| PrimePowerBinomial::new(p, e, max_n))
218            .collect();
219        Self { ppbs }
220    }
More examples
Hide additional examples
crates/competitive/src/math/prime_factors.rs (line 114)
112pub fn divisors(n: u64) -> Vec<u64> {
113    let mut d = vec![1u64];
114    for (p, c) in prime_factors(n) {
115        let k = d.len();
116        let mut acc = 1;
117        for _ in 0..c {
118            acc *= p;
119            for i in 0..k {
120                d.push(d[i] * acc);
121            }
122        }
123    }
124    d.sort_unstable();
125    d
126}
crates/competitive/src/math/primitive_root.rs (line 8)
3pub fn primitive_root(p: u64) -> u64 {
4    if p == 2 {
5        return 1;
6    }
7    let phi = p - 1;
8    let pf = prime_factors(phi);
9    let br = BarrettReduction::<u128>::new(p as _);
10    for g in 2..=3.min(p - 1) {
11        if check_primitive_root(g, phi, &br, &pf) {
12            return g;
13        }
14    }
15    let mut rng = Xorshift::default();
16    loop {
17        let g = ((rng.rand64() as u128 * (p - 2) as u128) >> 64) as u64 + 2;
18        if check_primitive_root(g, phi, &br, &pf) {
19            return g;
20        }
21    }
22}
crates/competitive/src/math/pow_prec.rs (line 20)
18    pub fn new(a: MInt<M>) -> Self {
19        let mut maxe = 0;
20        let period: u64 = prime_factors(M::mod_into() as u64)
21            .into_iter()
22            .map(|(p, e)| {
23                maxe = maxe.max(e);
24                p.pow(e - 1) * (p - 1)
25            })
26            .product();
27        let period = period as usize;
28        let sqn = ((period as f64).sqrt() as usize).max(maxe as usize) + 1;
29        let mut p0 = Vec::with_capacity(sqn);
30        let mut p1 = Vec::with_capacity(sqn);
31        let mut acc = MInt::<M>::one();
32        for _ in 0..sqn {
33            p0.push(acc);
34            acc *= a;
35        }
36        let b = acc;
37        acc = MInt::<M>::one();
38        for _ in 0..sqn {
39            p1.push(acc);
40            acc *= b;
41        }
42        Self {
43            period,
44            sqn,
45            p0,
46            p1,
47        }
48    }
crates/competitive/src/math/discrete_logarithm.rs (line 434)
381fn discrete_logarithm_prime_power(a: u64, b: u64, p: u64, e: u32) -> Option<(u64, u64)> {
382    assert_ne!(p, 0);
383    assert_ne!(e, 0);
384    let n = p.pow(e);
385    assert!(a < n);
386    assert!(b < n);
387    assert_eq!(gcd(a, p), 1);
388    if p == 1 {
389        return Some((0, 1));
390    }
391    if a == 0 {
392        return if b == 0 { Some((1, 1)) } else { None };
393    }
394    if b == 0 {
395        return None;
396    }
397    if e == 1 {
398        return IC.with(|ic| unsafe { &mut *ic.get() }.discrete_logarithm(a, b, p));
399    }
400    let br = BarrettReduction::<u128>::new(n as _);
401    if p == 2 {
402        if e >= 3 {
403            if a % 4 == 1 && b % 4 != 1 {
404                return None;
405            }
406            let aa = if a % 4 == 1 { a } else { n - a };
407            let bb = if b % 4 == 1 { b } else { n - b };
408            let g = 5;
409            let ord = n / 4;
410            let x = pohlig_hellman_prime_power_order(g, aa, n, p, e - 2)?;
411            let y = pohlig_hellman_prime_power_order(g, bb, n, p, e - 2)?;
412            let t = solve_linear_congruence(x, y, ord)?;
413            match (a % 4 == 1, b % 4 == 1) {
414                (true, true) => Some(t),
415                (false, true) if t.0 % 2 == 0 => Some((t.0, lcm(t.1, 2))),
416                (false, false) if t.0 % 2 == 1 => Some((t.0, lcm(t.1, 2))),
417                (false, false) if a == b => Some((1, lcm(t.1, 2))),
418                _ => None,
419            }
420        } else if a == 1 {
421            if b == 1 { Some((0, 1)) } else { None }
422        } else {
423            assert_eq!(a, 3);
424            if b == 1 {
425                Some((0, 2))
426            } else if b == 3 {
427                Some((1, 2))
428            } else {
429                None
430            }
431        }
432    } else {
433        let ord = n - n / p;
434        let pf_ord = prime_factors(ord);
435        let g = (2..)
436            .find(|&g| check_primitive_root(g, ord, &br, &pf_ord))
437            .unwrap();
438        let mut pf_p = prime_factors(p - 1);
439        pf_p.push((p, e - 1));
440        let mut abm = vec![];
441        for (q, c) in pf_p {
442            let m = q.pow(c);
443            let d = ord / m;
444            let gg = pow(g, d, &br);
445            let aa = pow(a, d, &br);
446            let bb = pow(b, d, &br);
447            let x = pohlig_hellman_prime_power_order(gg, aa, n, q, c)?;
448            let y = pohlig_hellman_prime_power_order(gg, bb, n, q, c)?;
449            abm.push((x, y, m));
450        }
451        solve_linear_congruences(abm)
452    }
453}
454
455/// a^x ≡ b (mod n)
456pub fn discrete_logarithm(a: u64, b: u64, n: u64) -> Option<u64> {
457    let a = a % n;
458    let b = b % n;
459    let d = 2.max(64 - n.leading_zeros() as u64);
460    let mut pw = 1 % n;
461    for i in 0..d {
462        if pw == b {
463            return Some(i);
464        }
465        pw = (pw as u128 * a as u128 % n as u128) as u64;
466    }
467    let g = gcd(pw, n);
468    if !b.is_multiple_of(g) {
469        return None;
470    }
471    let n = n / g;
472    let b = (b as u128 * modinv(pw, n) as u128 % n as u128) as u64;
473    let pf = prime_factors(n);
474    let mut abm = vec![];
475    for (p, e) in pf {
476        let q = p.pow(e);
477        let x = discrete_logarithm_prime_power(a % q, b % q, p, e)?;
478        abm.push((1, x.0, x.1));
479    }
480    solve_linear_congruences(abm).map(|x| x.0 + d)
481}