Skip to main content

QuotientArray

Struct QuotientArray 

Source
pub struct QuotientArray<T> {
    n: u64,
    isqrtn: u64,
    data: Vec<T>,
}
Expand description

store with index ${\lfloor\frac{n}{i}\rfloor \mid i=1,2,\ldots,n}$

Fields§

§n: u64§isqrtn: u64§data: Vec<T>

Implementations§

Source§

impl<T> QuotientArray<T>
where T: Zero,

Source

pub fn zeros(n: u64) -> Self

Source§

impl<T> QuotientArray<T>

Source

pub fn index_iter(n: u64, isqrtn: u64) -> impl Iterator<Item = u64>

Examples found in repository?
crates/competitive/src/math/quotient_array.rs (line 54)
52    pub fn from_fn(n: u64, f: impl FnMut(u64) -> T) -> Self {
53        let isqrtn = (n as f64).sqrt().floor() as u64;
54        let data = Self::index_iter(n, isqrtn).map(f).collect();
55        Self { n, isqrtn, data }
56    }
57
58    /// convert $\sum_{i\leq n} f(i)$ to $\sum_{i\leq n, i\text{ is prime}} f(i)$
59    ///
60    /// constraints: $\mathrm{mul_p}(f(x))=f(px)$
61    pub fn lucy_dp<G>(mut self, mut mul_p: impl FnMut(T, u64) -> T) -> Self
62    where
63        G: Group<T = T>,
64    {
65        let max_n = self.isqrtn as u32;
66        with_prime_list(max_n, |pl| {
67            for p in pl.primes_lte(max_n) {
68                let p = u64::from(p);
69                let k = self.quotient_index(p - 1);
70                let p2 = p * p;
71                for (i, q) in Self::index_iter(self.n, self.isqrtn).enumerate() {
72                    if q < p2 {
73                        break;
74                    }
75                    let diff = mul_p(G::rinv_operate(&self[q / p], &self.data[k]), p);
76                    G::rinv_operate_assign(&mut self.data[i], &diff);
77                }
78            }
79        });
80        self
81    }
82
83    /// convert $\sum_{i\leq n, i\text{ is prime}} f(i)$ to $\sum_{i\leq n} f(i)$
84    pub fn min_25_sieve<R>(&self, mut f: impl FnMut(u64, u32) -> T) -> Self
85    where
86        T: Clone + One,
87        R: Ring<T = T, Additive: Invertible>,
88    {
89        let mut dp = self.clone();
90        let max_n = self.isqrtn as u32;
91        with_prime_list(max_n, |pl| {
92            for p in pl.primes_lte(max_n).rev() {
93                let p = u64::from(p);
94                let k = self.quotient_index(p);
95                for (i, q) in Self::index_iter(self.n, self.isqrtn).enumerate() {
96                    let mut pc = p;
97                    if pc * p > q {
98                        break;
99                    }
100                    let mut c = 1;
101                    while q / p >= pc {
102                        let x = R::mul(&f(p, c), &(R::sub(&dp[q / pc], &self.data[k])));
103                        let x = R::add(&x, &f(p, c + 1));
104                        dp.data[i] = R::add(&dp.data[i], &x);
105                        c += 1;
106                        pc *= p;
107                    }
108                }
109            }
110        });
111        for x in &mut dp.data {
112            *x = R::add(x, &T::one());
113        }
114        dp
115    }
Source

pub fn map<U>(&self, f: impl FnMut(&T) -> U) -> QuotientArray<U>

Examples found in repository?
crates/library_checker/src/number_theory/sum_of_totient_function.rs (line 17)
9pub fn sum_of_totient_function(reader: impl Read, writer: impl Write) {
10    prepare_io!(reader, writer);
11    sc!(n: u64);
12    let mut s = 1;
13    let mut pp = 0;
14    let mut pc = 0;
15    let inv2 = M::new(2).inv();
16    let qa = QuotientArray::from_fn(n, |i| [M::from(i), M::from(i) * M::from(i + 1) * inv2])
17        .map(|[x, y]| [x - M::one(), y - M::one()])
18        .lucy_dp::<ArrayOperation<AdditiveOperation<_>, 2>>(|[x, y], p| [x, y * M::from(p)])
19        .map(|[x, y]| y - x)
20        .min_25_sieve::<AddMulOperation<_>>(|p, c| {
21            if pp != p || pc > c {
22                pp = p;
23                pc = 1;
24                s = p - 1;
25            }
26            while pc < c {
27                pc += 1;
28                s *= p;
29            }
30            M::from(s)
31        });
32    pp!(qa[n]);
33}
Source

pub fn quotient_index(&self, i: u64) -> usize

Examples found in repository?
crates/competitive/src/math/quotient_array.rs (line 69)
61    pub fn lucy_dp<G>(mut self, mut mul_p: impl FnMut(T, u64) -> T) -> Self
62    where
63        G: Group<T = T>,
64    {
65        let max_n = self.isqrtn as u32;
66        with_prime_list(max_n, |pl| {
67            for p in pl.primes_lte(max_n) {
68                let p = u64::from(p);
69                let k = self.quotient_index(p - 1);
70                let p2 = p * p;
71                for (i, q) in Self::index_iter(self.n, self.isqrtn).enumerate() {
72                    if q < p2 {
73                        break;
74                    }
75                    let diff = mul_p(G::rinv_operate(&self[q / p], &self.data[k]), p);
76                    G::rinv_operate_assign(&mut self.data[i], &diff);
77                }
78            }
79        });
80        self
81    }
82
83    /// convert $\sum_{i\leq n, i\text{ is prime}} f(i)$ to $\sum_{i\leq n} f(i)$
84    pub fn min_25_sieve<R>(&self, mut f: impl FnMut(u64, u32) -> T) -> Self
85    where
86        T: Clone + One,
87        R: Ring<T = T, Additive: Invertible>,
88    {
89        let mut dp = self.clone();
90        let max_n = self.isqrtn as u32;
91        with_prime_list(max_n, |pl| {
92            for p in pl.primes_lte(max_n).rev() {
93                let p = u64::from(p);
94                let k = self.quotient_index(p);
95                for (i, q) in Self::index_iter(self.n, self.isqrtn).enumerate() {
96                    let mut pc = p;
97                    if pc * p > q {
98                        break;
99                    }
100                    let mut c = 1;
101                    while q / p >= pc {
102                        let x = R::mul(&f(p, c), &(R::sub(&dp[q / pc], &self.data[k])));
103                        let x = R::add(&x, &f(p, c + 1));
104                        dp.data[i] = R::add(&dp.data[i], &x);
105                        c += 1;
106                        pc *= p;
107                    }
108                }
109            }
110        });
111        for x in &mut dp.data {
112            *x = R::add(x, &T::one());
113        }
114        dp
115    }
116}
117
118impl<T> Index<u64> for QuotientArray<T> {
119    type Output = T;
120    fn index(&self, i: u64) -> &Self::Output {
121        unsafe { self.data.get_unchecked(self.quotient_index(i)) }
122    }
123}
124
125impl<T> IndexMut<u64> for QuotientArray<T> {
126    fn index_mut(&mut self, index: u64) -> &mut Self::Output {
127        let i = self.quotient_index(index);
128        unsafe { self.data.get_unchecked_mut(i) }
129    }
Source

pub fn from_fn(n: u64, f: impl FnMut(u64) -> T) -> Self

Examples found in repository?
crates/competitive/src/math/quotient_array.rs (line 17)
16    pub fn zeros(n: u64) -> Self {
17        Self::from_fn(n, |_| T::zero())
18    }
More examples
Hide additional examples
crates/library_checker/src/number_theory/counting_primes.rs (line 8)
5pub fn counting_primes(reader: impl Read, writer: impl Write) {
6    prepare_io!(reader, writer);
7    sc!(n: u64);
8    let qa = QuotientArray::from_fn(n, |i| i as i64 - 1).lucy_dp::<AdditiveOperation<_>>(|x, _p| x);
9    pp!(qa[n]);
10}
crates/library_checker/src/number_theory/sum_of_totient_function.rs (line 16)
9pub fn sum_of_totient_function(reader: impl Read, writer: impl Write) {
10    prepare_io!(reader, writer);
11    sc!(n: u64);
12    let mut s = 1;
13    let mut pp = 0;
14    let mut pc = 0;
15    let inv2 = M::new(2).inv();
16    let qa = QuotientArray::from_fn(n, |i| [M::from(i), M::from(i) * M::from(i + 1) * inv2])
17        .map(|[x, y]| [x - M::one(), y - M::one()])
18        .lucy_dp::<ArrayOperation<AdditiveOperation<_>, 2>>(|[x, y], p| [x, y * M::from(p)])
19        .map(|[x, y]| y - x)
20        .min_25_sieve::<AddMulOperation<_>>(|p, c| {
21            if pp != p || pc > c {
22                pp = p;
23                pc = 1;
24                s = p - 1;
25            }
26            while pc < c {
27                pc += 1;
28                s *= p;
29            }
30            M::from(s)
31        });
32    pp!(qa[n]);
33}
Source

pub fn lucy_dp<G>(self, mul_p: impl FnMut(T, u64) -> T) -> Self
where G: Group<T = T>,

convert $\sum_{i\leq n} f(i)$ to $\sum_{i\leq n, i\text{ is prime}} f(i)$

constraints: $\mathrm{mul_p}(f(x))=f(px)$

Examples found in repository?
crates/library_checker/src/number_theory/counting_primes.rs (line 8)
5pub fn counting_primes(reader: impl Read, writer: impl Write) {
6    prepare_io!(reader, writer);
7    sc!(n: u64);
8    let qa = QuotientArray::from_fn(n, |i| i as i64 - 1).lucy_dp::<AdditiveOperation<_>>(|x, _p| x);
9    pp!(qa[n]);
10}
More examples
Hide additional examples
crates/library_checker/src/number_theory/sum_of_totient_function.rs (line 18)
9pub fn sum_of_totient_function(reader: impl Read, writer: impl Write) {
10    prepare_io!(reader, writer);
11    sc!(n: u64);
12    let mut s = 1;
13    let mut pp = 0;
14    let mut pc = 0;
15    let inv2 = M::new(2).inv();
16    let qa = QuotientArray::from_fn(n, |i| [M::from(i), M::from(i) * M::from(i + 1) * inv2])
17        .map(|[x, y]| [x - M::one(), y - M::one()])
18        .lucy_dp::<ArrayOperation<AdditiveOperation<_>, 2>>(|[x, y], p| [x, y * M::from(p)])
19        .map(|[x, y]| y - x)
20        .min_25_sieve::<AddMulOperation<_>>(|p, c| {
21            if pp != p || pc > c {
22                pp = p;
23                pc = 1;
24                s = p - 1;
25            }
26            while pc < c {
27                pc += 1;
28                s *= p;
29            }
30            M::from(s)
31        });
32    pp!(qa[n]);
33}
Source

pub fn min_25_sieve<R>(&self, f: impl FnMut(u64, u32) -> T) -> Self
where T: Clone + One, R: Ring<T = T, Additive: Invertible>,

convert $\sum_{i\leq n, i\text{ is prime}} f(i)$ to $\sum_{i\leq n} f(i)$

Examples found in repository?
crates/library_checker/src/number_theory/sum_of_totient_function.rs (lines 20-31)
9pub fn sum_of_totient_function(reader: impl Read, writer: impl Write) {
10    prepare_io!(reader, writer);
11    sc!(n: u64);
12    let mut s = 1;
13    let mut pp = 0;
14    let mut pc = 0;
15    let inv2 = M::new(2).inv();
16    let qa = QuotientArray::from_fn(n, |i| [M::from(i), M::from(i) * M::from(i + 1) * inv2])
17        .map(|[x, y]| [x - M::one(), y - M::one()])
18        .lucy_dp::<ArrayOperation<AdditiveOperation<_>, 2>>(|[x, y], p| [x, y * M::from(p)])
19        .map(|[x, y]| y - x)
20        .min_25_sieve::<AddMulOperation<_>>(|p, c| {
21            if pp != p || pc > c {
22                pp = p;
23                pc = 1;
24                s = p - 1;
25            }
26            while pc < c {
27                pc += 1;
28                s *= p;
29            }
30            M::from(s)
31        });
32    pp!(qa[n]);
33}

Trait Implementations§

Source§

impl<T: Clone> Clone for QuotientArray<T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Debug> Debug for QuotientArray<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T> Index<u64> for QuotientArray<T>

Source§

type Output = T

The returned type after indexing.
Source§

fn index(&self, i: u64) -> &Self::Output

Performs the indexing (container[index]) operation. Read more
Source§

impl<T> IndexMut<u64> for QuotientArray<T>

Source§

fn index_mut(&mut self, index: u64) -> &mut Self::Output

Performs the mutable indexing (container[index]) operation. Read more

Auto Trait Implementations§

§

impl<T> Freeze for QuotientArray<T>
where Vec<T>: Freeze,

§

impl<T> RefUnwindSafe for QuotientArray<T>
where Vec<T>: RefUnwindSafe,

§

impl<T> Send for QuotientArray<T>
where Vec<T>: Send,

§

impl<T> Sync for QuotientArray<T>
where Vec<T>: Sync,

§

impl<T> Unpin for QuotientArray<T>
where Vec<T>: Unpin,

§

impl<T> UnsafeUnpin for QuotientArray<T>
where Vec<T>: UnsafeUnpin,

§

impl<T> UnwindSafe for QuotientArray<T>
where Vec<T>: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToArrayVecScalar for T

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.