Problem p04024 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <numeric>
#include <set>
#include <string>
#include <vector>
using namespace std;

#ifdef LOCAL
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
#define eprintf(...) 42
#endif

typedef long long int int64;

const int MOD = (int)1e9 + 7;

void sadd(int &a, int b) {
  a += b;
  if (a >= MOD)
    a -= MOD;
}
int add(int a, int b) {
  sadd(a, b);
  return a;
}
void ssub(int &a, int b) {
  a -= b;
  if (a < 0)
    a += MOD;
}
int sub(int a, int b) {
  ssub(a, b);
  return a;
}
int mul(int a, int b) { return (a * 1LL * b) % MOD; }

int fpow(int x, int n) {
  if (n == 0)
    return 1;
  int a = fpow(x, n >> 1);
  a = mul(a, a);
  if (n & 1)
    a = mul(a, x);
  return a;
}

const int K = 2;

struct Matr {
  long long a[K][K];

  Matr(int mid = 0) : a() {
    for (int i = 0; i < K; i++)
      a[i][i] = mid;
  }

  Matr operator*(const Matr &A) const {
    Matr ans = Matr();
    for (int i = 0; i < K; i++)
      for (int j = 0; j < K; j++) {
        for (int h = 0; h < K; h++)
          ans.a[i][j] += a[i][h] * A.a[h][j];
        ans.a[i][j] %= MOD;
      }
    return ans;
  }

  Matr fpow(long long n) const {
    if (n == 0)
      return Matr(1);
    Matr A = fpow(n >> 1);
    A = A * A;
    if (n & 1)
      A = A * *this;
    return A;
  }
};

const int N = 1005;
char f[N][N];

int main(int, char **) {
#ifdef LOCAL
  freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif

  int n, m;
  long long k;
  scanf("%d%d%lld", &n, &m, &k);

  for (int i = 0; i < n; i++)
    scanf("%s", f[i]);

  int cnt = 0;
  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++)
      cnt += (f[i][j] == '#');

  int cntV = 0, cntH = 0;
  int neiH = 0, neiV = 0;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m - 1; j++)
      neiH += (f[i][j] == '#' && f[i][j + 1] == '#');
    cntH += (f[i][0] == '#' && f[i][m - 1] == '#');
  }

  for (int j = 0; j < m; j++) {
    for (int i = 0; i < n - 1; i++)
      neiV += (f[i][j] == '#' && f[i + 1][j] == '#');
    cntV += (f[0][j] == '#' && f[n - 1][j] == '#');
  }

  if ((cntH && cntV) || k == 0) {
    printf("1\n");
    return 0;
  }

  if (!cntH && !cntV) {
    printf("%d\n", fpow(cnt, k - 1));
    return 0;
  }

  if (cntH == 0) {
    cntH = cntV;
    neiH = neiV;
  }

  // eprintf("!! cnt = %d, k = %lld, neiH = %d, cntH = %d\n", cnt, k, neiH,
  // cntH);

  Matr M;
  M.a[0][0] = cnt;
  M.a[1][0] = sub(0, neiH);
  M.a[0][1] = 0;
  M.a[1][1] = cntH;

  Matr XM = M.fpow(k - 1);

  printf("%d\n", add(XM.a[0][0], XM.a[1][0]));

  return 0;
}


Fixed submission:
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <numeric>
#include <set>
#include <string>
#include <vector>
using namespace std;

#ifdef LOCAL
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
#define eprintf(...) 42
#endif

typedef long long int int64;

const int MOD = (int)1e9 + 7;

void sadd(int &a, int b) {
  a += b;
  if (a >= MOD)
    a -= MOD;
}
int add(int a, int b) {
  sadd(a, b);
  return a;
}
void ssub(int &a, int b) {
  a -= b;
  if (a < 0)
    a += MOD;
}
int sub(int a, int b) {
  ssub(a, b);
  return a;
}
int mul(int a, int b) { return (a * 1LL * b) % MOD; }

int fpow(int x, long long n) {
  if (n == 0)
    return 1;
  int a = fpow(x, n >> 1);
  a = mul(a, a);
  if (n & 1)
    a = mul(a, x);
  return a;
}

const int K = 2;

struct Matr {
  long long a[K][K];

  Matr(int mid = 0) : a() {
    for (int i = 0; i < K; i++)
      a[i][i] = mid;
  }

  Matr operator*(const Matr &A) const {
    Matr ans = Matr();
    for (int i = 0; i < K; i++)
      for (int j = 0; j < K; j++) {
        for (int h = 0; h < K; h++)
          ans.a[i][j] += a[i][h] * A.a[h][j];
        ans.a[i][j] %= MOD;
      }
    return ans;
  }

  Matr fpow(long long n) const {
    if (n == 0)
      return Matr(1);
    Matr A = fpow(n >> 1);
    A = A * A;
    if (n & 1)
      A = A * *this;
    return A;
  }
};

const int N = 1005;
char f[N][N];

int main(int, char **) {
#ifdef LOCAL
  freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif

  int n, m;
  long long k;
  scanf("%d%d%lld", &n, &m, &k);

  for (int i = 0; i < n; i++)
    scanf("%s", f[i]);

  int cnt = 0;
  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++)
      cnt += (f[i][j] == '#');

  int cntV = 0, cntH = 0;
  int neiH = 0, neiV = 0;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m - 1; j++)
      neiH += (f[i][j] == '#' && f[i][j + 1] == '#');
    cntH += (f[i][0] == '#' && f[i][m - 1] == '#');
  }

  for (int j = 0; j < m; j++) {
    for (int i = 0; i < n - 1; i++)
      neiV += (f[i][j] == '#' && f[i + 1][j] == '#');
    cntV += (f[0][j] == '#' && f[n - 1][j] == '#');
  }

  if ((cntH && cntV) || k == 0) {
    printf("1\n");
    return 0;
  }

  if (!cntH && !cntV) {
    printf("%d\n", fpow(cnt, k - 1));
    return 0;
  }

  if (cntH == 0) {
    cntH = cntV;
    neiH = neiV;
  }

  // eprintf("!! cnt = %d, k = %lld, neiH = %d, cntH = %d\n", cnt, k, neiH,
  // cntH);

  Matr M;
  M.a[0][0] = cnt;
  M.a[1][0] = sub(0, neiH);
  M.a[0][1] = 0;
  M.a[1][1] = cntH;

  Matr XM = M.fpow(k - 1);

  printf("%d\n", add(XM.a[0][0], XM.a[1][0]));

  return 0;
}