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 C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.IO;
using System.Text;
using System.Diagnostics;

using Binary = System.Func<System.Linq.Expressions.ParameterExpression, System.Linq.Expressions.ParameterExpression, System.Linq.Expressions.BinaryExpression>;
using Unary = System.Func<System.Linq.Expressions.ParameterExpression, System.Linq.Expressions.UnaryExpression>;

class Program
{
    static StreamWriter sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
    static Scan sc = new Scan();
//    static Scan sc = new ScanCHK();
    const int M = 1000000007;
    const double eps = 1e-9;
    static readonly int[] dd = { 0, 1, 0, -1, 0 };
    static void Main()
    {
        long n;
        int m, q;
        sc.Multi(out n, out m, out q);
        var a = sc.IntArr;
        var blk = new bool[m];
        foreach (var item in a)
        {
            blk[item] = true;
        }
        if (m % 7 == 0)
        {
            var uf = new UnionFind(m);
            for (int i = 0; i < m; i++)
            {
                if (!blk[i] && i % 7 < 6 && !blk[i + 1])
                {
                    uf.union(i, i + 1);
                }
                if (!blk[i] && i + 7 < m && !blk[i + 7])
                {
                    uf.union(i, i + 7);
                }
            }
            long cnt = 0;
            for (int i = 0; i < m; i++)
            {
                if (!blk[i] && uf.getpar(i) == i)
                {
                    ++cnt;
                }
            }
            var uff = new UnionFind(m * 2);
            for (int i = 0; i < 7; i++)
            {
                if (!blk[i] && !blk[m - 7 + i])
                {
                    uff.union(uf.getpar(i), uf.getpar(m - 7 + i) + m);
                }
            }
            long dis = 0;
            for (int i = 0; i < m * 2; i++)
            {
                if (uff.getpar(i) != i)
                {
                    ++dis;
                }
            }
            DBG(n * 7 / m * cnt - (n * 7 / m - 1) * dis);
            return;
        }
        else
        {
            var uf = new UnionFind(m * 7);
            for (int i = 0; i < m * 7; i++)
            {
                if (!blk[i % m] && i % 7 < 6 && !blk[(i + 1) % m])
                {
                    uf.union(i, i + 1);
                }
                if (!blk[i % m] && i + 7 < m * 7 && !blk[(i + 7) % m])
                {
                    uf.union(i, i + 7);
                }
            }
            long cnt = 0;
            for (int i = 0; i < m * 7; i++)
            {
                if (!blk[i % m] && uf.getpar(i) == i)
                {
                    ++cnt;
                }
            }
            var uff = new UnionFind(m * 14);
            for (int i = 0; i < 7; i++)
            {
                if (!blk[i % m] && !blk[(m * 7 - 7 + i) % m])
                {
                    uff.union(uf.getpar(i), uf.getpar(m * 7 - 7 + i) + m * 7);
                }
            }
            long dis = 0;
            for (int i = 0; i < m * 14; i++)
            {
                if (uff.getpar(i) != i)
                {
                    ++dis;
                }
            }
            DBG(n / m * cnt - (n / m - 1) * dis);
            return;
        }

        sw.Flush();
    }

    static void swap<T>(ref T a, ref T b) { var t = a; a = b; b = t; }
    static T Max<T>(params T[] a) { return a.Max(); }
    static T Min<T>(params T[] a) { return a.Min(); }
    static void DBG(string a) { Console.WriteLine(a); }
    static void DBG<T>(IEnumerable<T> a) { Console.WriteLine(string.Join(" ", a)); }
    static void DBG(params object[] a) { Console.WriteLine(string.Join(" ", a)); }
    static void Prt(string a) { sw.WriteLine(a); }
    static void Prt<T>(IEnumerable<T> a) { sw.WriteLine(string.Join(" ", a)); }
    static void Prt(params object[] a) { sw.WriteLine(string.Join(" ", a)); }
}
static class ex
{
    public static void swap<T>(this IList<T> a, int i, int j) { var t = a[i]; a[i] = a[j]; a[j] = t; }
    public static T[] copy<T>(this IList<T> a)
    {
        var ret = new T[a.Count];
        for (int i = 0; i < a.Count; i++) ret[i] = a[i];
        return ret;
    }
}
static class Operator<T>
{
    static readonly ParameterExpression x = Expression.Parameter(typeof(T), "x");
    static readonly ParameterExpression y = Expression.Parameter(typeof(T), "y");
    public static readonly Func<T, T, T> Add = Lambda(Expression.Add);
    public static readonly Func<T, T, T> Subtract = Lambda(Expression.Subtract);
    public static readonly Func<T, T, T> Multiply = Lambda(Expression.Multiply);
    public static readonly Func<T, T, T> Divide = Lambda(Expression.Divide);
    public static readonly Func<T, T> Plus = Lambda(Expression.UnaryPlus);
    public static readonly Func<T, T> Negate = Lambda(Expression.Negate);
    public static Func<T, T, T> Lambda(Binary op) { return Expression.Lambda<Func<T, T, T>>(op(x, y), x, y).Compile(); }
    public static Func<T, T> Lambda(Unary op) { return Expression.Lambda<Func<T, T>>(op(x), x).Compile(); }
}

class ScanCHK : Scan
{
    public new string Str { get { var s = Console.ReadLine(); if (s != s.Trim()) throw new Exception(); return s; } }
}
class Scan
{
    public int Int { get { return int.Parse(Str); } }
    public long Long { get { return long.Parse(Str); } }
    public double Double { get { return double.Parse(Str); } }
    public string Str { get { return Console.ReadLine().Trim(); } }
    public int[] IntArr { get { return StrArr.Select(int.Parse).ToArray(); } }
    public long[] LongArr { get { return StrArr.Select(long.Parse).ToArray(); } }
    public double[] DoubleArr { get { return StrArr.Select(double.Parse).ToArray(); } }
    public string[] StrArr { get { return Str.Split(); } }
    bool eq<T, U>() { return typeof(T).Equals(typeof(U)); }
    T ct<T, U>(U a) { return (T)Convert.ChangeType(a, typeof(T)); }
    T cv<T>(string s) { return eq<T, int>()    ? ct<T, int>(int.Parse(s))
                             : eq<T, long>()   ? ct<T, long>(long.Parse(s))
                             : eq<T, double>() ? ct<T, double>(double.Parse(s))
                             : eq<T, char>()   ? ct<T, char>(s[0])
                                               : ct<T, string>(s); }
    public void Multi<T>(out T a) { a = cv<T>(Str); }
    public void Multi<T, U>(out T a, out U b)
    { var ar = StrArr; a = cv<T>(ar[0]); b = cv<U>(ar[1]); }
    public void Multi<T, U, V>(out T a, out U b, out V c)
    { var ar = StrArr; a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]); }
    public void Multi<T, U, V, W>(out T a, out U b, out V c, out W d)
    { var ar = StrArr; a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]); d = cv<W>(ar[3]); }
    public void Multi<T, U, V, W, X>(out T a, out U b, out V c, out W d, out X e)
    { var ar = StrArr; a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]); d = cv<W>(ar[3]); e = cv<X>(ar[4]); }
}
class mymath
{
    public static long Mod = 1000000007;
    public static bool isprime(long a)
    {
        if (a < 2) return false;
        for (long i = 2; i * i <= a; i++) if (a % i == 0) return false;
        return true;
    }
    public static bool[] sieve(int n)
    {
        var p = new bool[n + 1];
        for (int i = 2; i <= n; i++) p[i] = true;
        for (int i = 2; i * i <= n; i++) if (p[i]) for (int j = i * i; j <= n; j += i) p[j] = false;
        return p;
    }
    public static List<int> getprimes(int n)
    {
        var prs = new List<int>();
        var p = sieve(n);
        for (int i = 2; i <= n; i++) if (p[i]) prs.Add(i);
        return prs;
    }
    public static long[][] E(int n)
    {
        var ret = new long[n][];
        for (int i = 0; i < n; i++) { ret[i] = new long[n]; ret[i][i] = 1; }
        return ret;
    }
    public static long[][] pow(long[][] A, long n)
    {
        if (n == 0) return E(A.Length);
        var t = pow(A, n / 2);
        if ((n & 1) == 0) return mul(t, t);
        return mul(mul(t, t), A);
    }
    public static double dot(double[] x, double[] y)
    {
        int n = x.Length;
        double ret = 0;
        for (int i = 0; i < n; i++) ret += x[i] * y[i];
        return ret;
    }
    public static long dot(long[] x, long[] y)
    {
        int n = x.Length;
        long ret = 0;
        for (int i = 0; i < n; i++) ret = (ret + x[i] * y[i]) % Mod;
        return ret;
    }
    public static T[][] trans<T>(T[][] A)
    {
        int n = A[0].Length, m = A.Length;
        var ret = new T[n][];
        for (int i = 0; i < n; i++) { ret[i] = new T[m]; for (int j = 0; j < m; j++) ret[i][j] = A[j][i]; }
        return ret;
    }
    public static double[] mul(double[][] A, double[] x)
    {
        int n = A.Length;
        var ret = new double[n];
        for (int i = 0; i < n; i++) ret[i] = dot(x, A[i]);
        return ret;
    }
    public static long[] mul(long[][] A, long[] x)
    {
        int n = A.Length;
        var ret = new long[n];
        for (int i = 0; i < n; i++) ret[i] = dot(x, A[i]);
        return ret;
    }
    public static long[][] mul(long[][] A, long[][] B)
    {
        int n = A.Length;
        var Bt = trans(B);
        var ret = new long[n][];
        for (int i = 0; i < n; i++) ret[i] = mul(Bt, A[i]);
        return ret;
    }
    public static long[] add(long[] x, long[] y)
    {
        int n = x.Length;
        var ret = new long[n];
        for (int i = 0; i < n; i++) ret[i] = (x[i] + y[i]) % Mod;
        return ret;
    }
    public static long[][] add(long[][] A, long[][] B)
    {
        int n = A.Length;
        var ret = new long[n][];
        for (int i = 0; i < n; i++) ret[i] = add(A[i], B[i]);
        return ret;
    }
    public static long pow(long a, long b)
    {
        if (a >= Mod) return pow(a % Mod, b);
        if (a == 0) return 0;
        if (b == 0) return 1;
        var t = pow(a, b / 2);
        if ((b & 1) == 0) return t * t % Mod;
        return t * t % Mod * a % Mod;
    }
    public static long inv(long a) { return pow(a, Mod - 2); }
    public static long gcd(long a, long b)
    {
        while (b > 0) { var t = a % b; a = b; b = t; }
        return a;
    }
    // a x + b y = gcd(a, b)
    public static long extgcd(long a, long b, out long x, out long y)
    {
        long g = a; x = 1; y = 0;
        if (b > 0) { g = extgcd(b, a % b, out y, out x); y -= a / b * x; }
        return g;
    }
    public static long lcm(long a, long b) { return a / gcd(a, b) * b; }
    public static long comb(int n, int r)
    {
        if (n < 0 || r < 0 || r > n) return 0;
        if (n - r < r) r = n - r;
        if (r == 0) return 1;
        if (r == 1) return n;
        int[] numer = new int[r], denom = new int[r];
        for (int k = 0; k < r; k++) { numer[k] = n - r + k + 1; denom[k] = k + 1; }
        for (int p = 2; p <= r; p++)
        {
            int piv = denom[p - 1];
            if (piv > 1)
            {
                int ofst = (n - r) % p;
                for (int k = p - 1; k < r; k += p) { numer[k - ofst] /= piv; denom[k] /= piv; }
            }
        }
        long ret = 1;
        for (int k = 0; k < r; k++) if (numer[k] > 1) ret = ret * numer[k] % Mod;
        return ret;
    }
}
class UnionFind
{
    int n;
    int[] par, num;
    public UnionFind(int m)
    {
        n = m; par = new int[n]; num = new int[n];
        for (int i = 0; i < n; ++i) { par[i] = i; num[i] = 1; }
    }
    int find(int x) => par[x] == x ? x : (par[x] = find(par[x]));
    public bool isunion(int x, int y) => find(x) == find(y);
    public int unionnum(int x) => num[find(x)];
    public bool union(int x, int y)
    {
        int p = find(x), q = find(y);
        if (p == q) return false;
        par[q] = p; num[p] += num[q];
        return true;
    }
    public int getpar(int x) => find(x);
}