Problem:
Max Score: 500 Points

Problem Statement

We have a grid with n rows and 7 columns. We call it a calendar. The cell at i-th row and j-th column is denoted (i, j).

Initially, each cell at (i, j) contains the integer 7i + j - 8, and each cell is white.

Snuke likes painting, so he decided integer m, and did q operations with a calendar.

・In i-th operation, he paint black on the cell in which an integer is written such remainder of dividing by m is a_i.

Please count the number of connected white parts.

Note that if two adjacent cells are white, the cells belong to the same connected part.

Input Format

The input format is following:

n m q
a_1 a_2 ... a_q

Output Format

Print the number of connected part in one line.

Constraints

n ≤ 10^{12}

7n is divisible by m.

1 ≤ q ≤ m ≤ 10^5

0 ≤ a_1 < a_2 < ... < a_q < m

Scoring

Subtask 1 [100 points]

n ≤ 100000.

Subtask 2 [90 points]

m is divisible by 7.

a_{i + 1} - a_i = 1.

Subtask 3 [200 points]

m is divisible by 7.

Subtask 4 [110 points]

There are no additional constraints.

Sample Input 1

7 7 3
1 3 5

Sample Output 1

4

The calendar looks like this:

Sample Input 2

10 14 8
5 6 7 8 9 10 11 12

Sample Output 2

10

The calendar looks like this:

Solution in Rust (1.15.1) (judge verdict: Accepted)

#[allow(unused_imports)]
use std::cmp::*;
#[allow(unused_imports)]
use std::collections::*;
use std::io::Read;
#[allow(dead_code)]
fn getline() -> String {
    let mut ret = String::new();
    std::io::stdin().read_line(&mut ret).ok().unwrap();
    ret
}
fn get_word() -> String {
    let mut stdin = std::io::stdin();
    let mut u8b: [u8; 1] = [0];
    loop {
        let mut buf: Vec<u8> = Vec::with_capacity(16);
        loop {
            let res = stdin.read(&mut u8b);
            if res.unwrap_or(0) == 0 || u8b[0] <= b' ' {
                break;
            } else {
                buf.push(u8b[0]);
            }
        }
        if buf.len() >= 1 {
            let ret = String::from_utf8(buf).unwrap();
            return ret;
        }
    }
}

#[allow(dead_code)]
fn get<T: std::str::FromStr>() -> T { get_word().parse().ok().unwrap() }

/**
 * Union-Find tree.
 * Verified by yukicoder No.94 (http://yukicoder.me/submissions/82111)
 */
struct UnionFind { disj: Vec<usize> }

impl UnionFind {
    fn new(n: usize) -> Self {
        let mut disj = vec![0; n];
        for i in 0 .. n {
            disj[i] = i;
        }
        UnionFind { disj: disj }
    }
    fn root(self: &mut Self, x: usize) -> usize {
        if x != self.disj[x] {
            let par = self.disj[x];
            let r = self.root(par);
            self.disj[x] = r;
        }
        return self.disj[x];
    }
    fn unite(self: &mut Self, x: usize, y: usize) {
        let xr = self.root(x);
        let yr = self.root(y);
        self.disj[xr] = yr;
    }
    fn is_same_set(self: &mut Self, x: usize, y: usize) -> bool {
        return self.root(x) == self.root(y);
    }
}


fn backend(n: usize, m: usize, a: &[usize]) -> i64 {
    let mut tbl = vec![false; 7 * n];
    for &a in a.iter() {
        for j in 0 .. 7 * n / m {
            tbl[a + m * j] = true;
        }
    }
    let mut uf = UnionFind::new(7 * n);
    for i in 0 .. n {
        for j in 0 .. 7 {
            if i < n - 1 && !tbl[7 * i + j] && !tbl[7 * i + j + 7] {
                uf.unite(7 * i + j, 7 * i + j + 7);
            }
            if j < 6 && !tbl[7 * i + j] && !tbl[7 * i + j + 1] {
                uf.unite(7 * i + j, 7 * i + j + 1);
            }
        }
    }
    let mut s = HashSet::new();
    for i in 0 .. 7 * n {
        if !tbl[i] {
            s.insert(uf.root(i));
        }
    }
    s.len() as i64
}
fn solve_easy1(n: usize, m: usize, a: &[usize]) {
    let mut tbl = vec![false; 7 * n];
    for &a in a.iter() {
        for j in 0 .. 7 * n / m {
            tbl[a + m * j] = true;
        }
    }
    let mut uf = UnionFind::new(7 * n);
    for i in 0 .. n {
        for j in 0 .. 7 {
            if i < n - 1 && !tbl[7 * i + j] && !tbl[7 * i + j + 7] {
                uf.unite(7 * i + j, 7 * i + j + 7);
            }
            if j < 6 && !tbl[7 * i + j] && !tbl[7 * i + j + 1] {
                uf.unite(7 * i + j, 7 * i + j + 1);
            }
        }
    }
    let mut s = HashSet::new();
    for i in 0 .. 7 * n {
        if !tbl[i] {
            s.insert(uf.root(i));
        }
    }
    println!("{}", s.len());
}

fn solve() {
    let n: i64 = get();
    let m: usize = get();
    let q = get();
    let a: Vec<usize> = (0 .. q).map(|_| get()).collect();
    let tmp = if m % 7 == 0 { m } else { 7 * m };
    let s1 = backend(tmp / 7, m, &a);
    let s2 = backend(2 * tmp / 7, m, &a);
    println!("{}", s1 + (s2 - s1) * (7 * n / tmp as i64 - 1));
}

fn main() {
    // In order to avoid potential stack overflow, spawn a new thread.
    let stack_size = 104_857_600; // 100 MB
    let thd = std::thread::Builder::new().stack_size(stack_size);
    thd.spawn(|| solve()).unwrap().join().unwrap();
}