CSES - Putka Open 2020 – 4/5 - Results
Submission details
Task:Tekijät
Sender:Hennkka
Submission time:2020-11-06 23:53:59 +0200
Language:Rust
Status:READY
Result:100
Feedback
groupverdictscore
#1ACCEPTED12
#2ACCEPTED35
#3ACCEPTED53
Test results
testverdicttimegroup
#1ACCEPTED0.17 s1, 2, 3details
#2ACCEPTED0.17 s1, 2, 3details
#3ACCEPTED0.18 s2, 3details
#4ACCEPTED0.18 s3details
#5ACCEPTED0.21 s3details
#6ACCEPTED0.23 s3details
#7ACCEPTED0.17 s3details

Compiler report

warning: unused import: `rand::prelude::*`
 --> input/code.rs:1:5
  |
1 | use rand::prelude::*;
  |     ^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: unused import: `std::collections::BTreeMap`
 --> input/code.rs:2:5
  |
2 | use std::collections::BTreeMap;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: method is never used: `len`
  --> input/code.rs:25:5
   |
25 |     fn len(&self) -> usize {
   |     ^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default

warning: method is never used: `reduce`
   --> input/code.rs:115:5
    |
115 |     fn reduce(&self, a: u32) -> u32 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Code

use rand::prelude::*;
use std::collections::BTreeMap;
use std::io::BufRead;

#[derive(Clone, Copy, Debug)]
struct Svec {
    i: u8,
    data: [u32; 7],
}

impl Svec {
    fn new() -> Self {
        Self {
            i: 0,
            data: Default::default(),
        }
    }
    fn push(&mut self, v: u32) {
        self.data[self.i as usize] = v;
        self.i += 1;
    }
    fn is_empty(&self) -> bool {
        self.i == 0
    }
    fn len(&self) -> usize {
        self.i as usize
    }

    fn with_subsets<F: FnMut(&[u32])>(&self, f: F) {
        let mut f = f;
        let mut subset = [0u32; 7];
        for i1 in 0..self.i as usize {
            subset[0] = self.data[i1];
            f(&subset[0..1]);
            for i2 in i1 + 1..self.i as usize {
                subset[1] = self.data[i2];
                f(&subset[0..2]);
                for i3 in i2 + 1..self.i as usize {
                    subset[2] = self.data[i3];
                    f(&subset[0..3]);
                    for i4 in i3 + 1..self.i as usize {
                        subset[3] = self.data[i4];
                        f(&subset[0..4]);
                        for i5 in i4 + 1..self.i as usize {
                            subset[4] = self.data[i5];
                            f(&subset[0..5]);
                            for i6 in i5 + 1..self.i as usize {
                                subset[5] = self.data[i6];
                                f(&subset[0..6]);
                                for i7 in i6 + 1..self.i as usize {
                                    // TODO: Replace by if condition
                                    subset[6] = self.data[i7];
                                    f(&subset[0..7]);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

struct Sieve {
    // sieve: Vec<Option<NonZeroUsize>>,
    prime_factors: Vec<Svec>,
}

impl Iterator for Svec {
    type Item = u32;
    fn next(&mut self) -> Option<Self::Item> {
        if self.is_empty() {
            None
        } else {
            self.i -= 1;
            Some(self.data[self.i as usize])
        }
    }
}

impl Sieve {
    fn new(n: u32) -> Self {
        let mut prime_factors = vec![Svec::new(); n as usize + 1];
        for i in 2..=n {
            if prime_factors[i as usize].is_empty() {
                // Prime
                for j in (1..).take_while(|j| *j * i <= n) {
                    prime_factors[(j * i) as usize].push(i);
                }
            }
        }

        Self { prime_factors }
    }

    // fn factors(&self, a: usize) -> Vec<usize> {
    //     let mut a = a;
    //     let mut res = Vec::new();
    //     while a > 1 {
    //         if let Some(p) = self.sieve[a] {
    //             res.push(p.get());
    //             a /= p.get();
    //         }
    //     }
    //     res
    // }

    fn unique_factors(&self, a: u32) -> Svec {
        // let mut f = self.factors(a);
        // f.dedup();
        // f
        self.prime_factors[a as usize]
    }

    fn reduce(&self, a: u32) -> u32 {
        self.unique_factors(a).product()
    }
}

fn main() {
    let sieve = Sieve::new(1_000_000);

    let stdin = std::io::stdin();
    let stdin = stdin.lock();
    let mut lines = stdin.lines();

    let n: usize = lines.next().unwrap().unwrap().parse().unwrap();
    let input: Vec<_> = lines
        .next()
        .unwrap()
        .unwrap()
        .split_whitespace()
        .map(|v| v.parse().unwrap())
        .map(|v| sieve.unique_factors(v))
        .collect();

    // Fill the count table
    let mut counts = vec![0; 1_000_000];
    let mut orig_counts = vec![0; 1_000_000];
    let mut dedup_input = Vec::with_capacity(100_000);
    for v in input {
        v.with_subsets(|s| counts[s.iter().product::<u32>() as usize] += 1);
        let vp = v.product::<u32>() as usize;
        if orig_counts[vp] == 0 {
            dedup_input.push(v);
        }
        orig_counts[vp] += 1;
    }

    // Count pairs
    let mut res = 0;
    for v in dedup_input {
        let mut subres = 0;
        // println!(
        //     "Handling {}, multiplier {}",
        //     v.product::<u32>(),
        //     orig_counts[v.product::<u32>() as usize]
        // );
        v.with_subsets(|s| {
            let c = counts[s.iter().product::<u32>() as usize] - 1;
            // println!("Subset {:?}, count {}", s, c);
            if s.len() % 2 == 0 {
                subres -= c;
            } else {
                subres += c;
            }
        });

        res += orig_counts[v.product::<u32>() as usize] * subres;
    }

    println!("{}", n * (n - 1) / 2 - res / 2);

    // println!("{:?}", input);
    // for _ in 0..t {
    //     let c: usize = lines.next().unwrap().unwrap().parse().unwrap();
    //     if solve(c) {
    //         println!("YES");
    //     } else {
    //         println!("NO");
    //     }
    // }
}

#[cfg(test)]
mod tests {
    use super::*;
}

Test details

Test 1

Group: 1, 2, 3

Verdict: ACCEPTED

input
100
1 2 3 4 5 6 7 8 9 10 11 12 13 ...

correct output
3043

user output
3043

Test 2

Group: 1, 2, 3

Verdict: ACCEPTED

input
100
71 19 26 18 57 78 80 89 31 26 ...

correct output
3086

user output
3086

Test 3

Group: 2, 3

Verdict: ACCEPTED

input
100000
66 87 90 67 93 89 57 29 34 4 8...

correct output
3044751906

user output
3044751906

Test 4

Group: 3

Verdict: ACCEPTED

input
100000
1 2 3 4 5 6 7 8 9 10 11 12 13 ...

correct output
3039650753

user output
3039650753

Test 5

Group: 3

Verdict: ACCEPTED

input
100000
238907 151373 522599 885657 37...

correct output
3031155756

user output
3031155756

Test 6

Group: 3

Verdict: ACCEPTED

input
100000
510510 510510 510510 510510 51...

correct output
0

user output
0

Test 7

Group: 3

Verdict: ACCEPTED

input
100000
999983 999983 999983 999983 99...

correct output
0

user output
0