Problem p03314 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <cstdio>
#include <cstring>

#define FILL(a, n, x) memset((a), (x), sizeof((a)[0]) * (n))
#define COPY(a, n, b) memcpy((b), (a), sizeof((a)[0]) * (n))
#define FILLA(a, x) memset((a), (x), sizeof(a))
#define COPYA(a, b) memcpy((b), (a), sizeof(a))

using namespace std;

typedef long long li;
typedef unsigned long long lu;
const li infl = ~0LLU >> 2;

template <class T> inline void Min(T &x, T y) {
  if (y < x)
    x = y;
}
template <class T> inline void Max(T &x, T y) {
  if (y > x)
    x = y;
}

const int mod = 1e9 + 7;
inline int Add(int x) { return x >= mod ? x - mod : x; }
inline void Add(int &x, int y) {
  x += y;
  if (x >= mod)
    x -= mod;
}
inline int Sub(int x) { return x < 0 ? x + mod : x; }
inline void Sub(int &x, int y) {
  x -= y;
  if (x < 0)
    x += mod;
}
inline int Mul(int x, int y) { return (int)((li)x * y % mod); }
inline int Mul(int x, int y, int z) { return Mul(x, Mul(y, z)); }
int Pow(int x, int y) {
  int z = 1;
  for (; y; y >>= 1) {
    if (y & 1)
      z = Mul(z, x);
    x = Mul(x, x);
  }
  return z;
}
int Inv(int x) { return Pow(x, mod - 2); }

// ----------------------------------------

const int maxn = 25000, maxk = 400;

int n, m, k;
int a[maxn];
int f[maxn + 1][maxk + 1], g[maxn + 1][maxk + 1];

void Init(void) {
  for (int i = 1; i < k; ++i) {
    f[0][i] = 1;
  }
  for (int j = 1; j <= n; ++j) {
    g[j - 1][0] = 0;
    for (int i = 1; i < k; ++i) {
      g[j - 1][i] = Add(g[j - 1][i - 1] + f[j - 1][i]);
    }
    for (int i = 1; i < k; ++i) {
      f[j][i] = g[j - 1][i];
      if (i + 1 < k) {
        Add(f[j][i], Mul(f[j - 1][i + 1], k - i));
      }
    }
  }
  for (int i = 1; i < k; ++i) {
    g[n][i] = Add(g[n][i - 1] + f[n][i]);
  }
}

int cnt[maxk];

bool Include(void) {
  for (int i = 0; i + k <= m; ++i) {
    FILL(cnt, k, 0);
    for (int j = 0; j < k; ++j) {
      cnt[a[i + j]] = 1;
    }
    if (count(cnt, cnt + k, 0) == 0) {
      return true;
    }
  }
  return false;
}

bool Diff(void) {
  FILL(cnt, k, 0);
  for (int i = 0; i < m; ++i) {
    ++cnt[a[i]];
  }
  for (int i = 0; i < k; ++i) {
    if (cnt[i] >= 2) {
      return false;
    }
  }
  return true;
}

int Solve1(void) {
  int L, R;
  FILL(cnt, k, 0);
  for (int i = 0; i < m; ++i) {
    if (++cnt[a[i]] >= 2) {
      L = i;
      break;
    }
  }
  FILL(cnt, k, 0);
  for (int i = m - 1; i >= 0; --i) {
    if (++cnt[a[i]] >= 2) {
      R = m - i - 1;
      break;
    }
  }

  int ans = 0;
  for (int i = 0; i + m <= n; ++i) {
    Add(ans, Mul(f[i][L], f[n - i - m][R]));
  }
  return ans;
}

int Solve2(void) {
  int ans = 0;
  for (int i = 0; i + m <= n; ++i) {
    // to the end
    if (i + m < k) {
      int prod = 1;
      for (int j = i - 1, x = k - m; j >= 0; --j, --x) {
        prod = Mul(prod, x);
      }
      Add(ans, Mul(prod, f[n - (i + m)][i + m]));
    }

    // other case
    int prod = 1, len = m, x = k - m;
    for (int l = i; l > 0; --l) {
      Add(ans, Mul(prod, f[n - (i + m)][len], g[l - 1][len]));
      ++len;
      prod = Mul(prod, x);
      --x;
    }
  }
  return ans;
}

int main(void) {
  scanf("%d%d%d", &n, &k, &m);
  for (int i = 0; i < m; ++i) {
    scanf("%d", a + i), --a[i];
  }
  Init();
  int total = Mul(n - m + 1, Pow(k, n - m)), ans = 0;

  if (Include()) {
    ans = 0;
  } else {
    if (Diff()) {
      ans = Solve2();
    } else {
      ans = Solve1();
    }
  }

  printf("%d\n", Sub(total - ans));
  return 0;
}


Fixed submission:
#include <algorithm>
#include <cstdio>
#include <cstring>

#define FILL(a, n, x) memset((a), (x), sizeof((a)[0]) * (n))
#define COPY(a, n, b) memcpy((b), (a), sizeof((a)[0]) * (n))
#define FILLA(a, x) memset((a), (x), sizeof(a))
#define COPYA(a, b) memcpy((b), (a), sizeof(a))

using namespace std;

typedef long long li;
typedef unsigned long long lu;
const li infl = ~0LLU >> 2;

template <class T> inline void Min(T &x, T y) {
  if (y < x)
    x = y;
}
template <class T> inline void Max(T &x, T y) {
  if (y > x)
    x = y;
}

const int mod = 1e9 + 7;
inline int Add(int x) { return x >= mod ? x - mod : x; }
inline void Add(int &x, int y) {
  x += y;
  if (x >= mod)
    x -= mod;
}
inline int Sub(int x) { return x < 0 ? x + mod : x; }
inline void Sub(int &x, int y) {
  x -= y;
  if (x < 0)
    x += mod;
}
inline int Mul(int x, int y) { return (int)((li)x * y % mod); }
inline int Mul(int x, int y, int z) { return Mul(x, Mul(y, z)); }
int Pow(int x, int y) {
  int z = 1;
  for (; y; y >>= 1) {
    if (y & 1)
      z = Mul(z, x);
    x = Mul(x, x);
  }
  return z;
}
int Inv(int x) { return Pow(x, mod - 2); }

// ----------------------------------------

const int maxn = 25000, maxk = 400;

int n, m, k;
int a[maxn];
int f[maxn + 1][maxk + 1], g[maxn + 1][maxk + 1];

void Init(void) {
  for (int i = 1; i < k; ++i) {
    f[0][i] = 1;
  }
  for (int j = 1; j <= n; ++j) {
    g[j - 1][0] = 0;
    for (int i = 1; i < k; ++i) {
      g[j - 1][i] = Add(g[j - 1][i - 1] + f[j - 1][i]);
    }
    for (int i = 1; i < k; ++i) {
      f[j][i] = g[j - 1][i];
      if (i + 1 < k) {
        Add(f[j][i], Mul(f[j - 1][i + 1], k - i));
      }
    }
  }
  for (int i = 1; i < k; ++i) {
    g[n][i] = Add(g[n][i - 1] + f[n][i]);
  }
}

int cnt[maxk];

bool Include(void) {
  for (int i = 0; i + k <= m; ++i) {
    FILL(cnt, k, 0);
    for (int j = 0; j < k; ++j) {
      cnt[a[i + j]] = 1;
    }
    if (count(cnt, cnt + k, 0) == 0) {
      return true;
    }
  }
  return false;
}

bool Diff(void) {
  FILL(cnt, k, 0);
  for (int i = 0; i < m; ++i) {
    ++cnt[a[i]];
  }
  for (int i = 0; i < k; ++i) {
    if (cnt[i] >= 2) {
      return false;
    }
  }
  return true;
}

int Solve1(void) {
  int L, R;
  FILL(cnt, k, 0);
  for (int i = 0; i < m; ++i) {
    if (++cnt[a[i]] >= 2) {
      L = i;
      break;
    }
  }
  FILL(cnt, k, 0);
  for (int i = m - 1; i >= 0; --i) {
    if (++cnt[a[i]] >= 2) {
      R = m - i - 1;
      break;
    }
  }

  int ans = 0;
  for (int i = 0; i + m <= n; ++i) {
    Add(ans, Mul(f[i][L], f[n - i - m][R]));
  }
  return ans;
}

int Solve2(void) {
  int ans = 0;
  for (int i = 0; i + m <= n; ++i) {
    // to the end
    if (i + m < k) {
      int prod = 1;
      for (int j = i - 1, x = k - m; j >= 0; --j, --x) {
        prod = Mul(prod, x);
      }
      Add(ans, Mul(prod, f[n - (i + m)][i + m]));
    }

    // other case
    int prod = 1, len = m, x = k - m;
    for (int l = i; l > 0 && len < k; --l) {
      Add(ans, Mul(prod, f[n - (i + m)][len], g[l - 1][len]));
      ++len;
      prod = Mul(prod, x);
      --x;
    }
  }
  return ans;
}

int main(void) {
  scanf("%d%d%d", &n, &k, &m);
  for (int i = 0; i < m; ++i) {
    scanf("%d", a + i), --a[i];
  }
  Init();
  int total = Mul(n - m + 1, Pow(k, n - m)), ans = 0;

  if (Include()) {
    ans = 0;
  } else {
    if (Diff()) {
      ans = Solve2();
    } else {
      ans = Solve1();
    }
  }

  printf("%d\n", Sub(total - ans));
  return 0;
}