Problem p04024 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#define inf 20021225
#define ll long long
#define mdn 1000000007
using namespace std;

struct matrix {
  int a[3][3], n;
};
inline void init(matrix &a) { memset(a.a, 0, sizeof(a.a)); }
matrix operator*(matrix a, matrix b) {
  matrix tmp;
  init(tmp);
  tmp.n = a.n;
  // printf("%d\n",tmp.a[2][2]);
  for (int i = 1; i <= a.n; i++)
    for (int j = 1; j <= a.n; j++)
      for (int k = 1; k <= a.n; k++)
        tmp.a[i][j] = ((ll)tmp.a[i][j] + (ll)a.a[i][k] * b.a[k][j] % mdn) % mdn;
  return tmp;
}

matrix ksm(matrix bs, ll mi) {
  matrix tmp;
  tmp.n = bs.n;
  init(tmp);
  for (int i = 1; i <= tmp.n; i++)
    tmp.a[i][i] = 1;
  while (mi) {
    if (mi & 1)
      tmp = tmp * bs;
    bs = bs * bs;
    mi >>= 1;
  }
  return tmp;
}
char mp[1100][1100];
int ud, lr, eud, elr, cnt;
int ksm(int bs, ll mi) {
  int ans = 1;
  while (mi) {
    if (mi & 1)
      ans = (ll)ans * bs % mdn;
    bs = (ll)bs * bs % mdn;
    mi >>= 1;
  }
  return ans;
}
int main() {
  int h, w;
  ll k;
  scanf("%d%d%lld", &h, &w, &k);
  for (int i = 1; i <= h; i++) {
    scanf("%s", mp[i] + 1);
    if (mp[i][1] == mp[i][w] && mp[i][1] == '#')
      lr++;
    for (int j = 2; j <= w; j++)
      if (mp[i][j] == mp[i][j - 1] && mp[i][j] == '#')
        elr++;
  }
  for (int i = 2; i <= h; i++)
    for (int j = 1; j <= w; j++)
      if (mp[i - 1][j] == mp[i][j] && mp[i][j] == '#')
        eud++;
  for (int i = 1; i <= w; i++)
    if (mp[1][i] == mp[h][i] && mp[h][i] == '#')
      ud++;
  for (int i = 1; i <= h; i++)
    for (int j = 1; j <= w; j++)
      cnt += (mp[i][j] == '#');
  if (lr && ud) {
    printf("1\n");
    return 0;
  }
  if (!lr && !ud) {
    printf("%d\n", ksm(cnt, k - 1));
    return 0;
  }
  // printf("QAQ");
  if (lr)
    swap(lr, ud), swap(elr, eud); // only ud
  matrix ans;
  ans.n = 2; // printf("%d %d\n",eud,ud);
  ans.a[1][1] = cnt;
  ans.a[1][2] = 0;
  ans.a[2][1] = 1;
  ans.a[2][2] = ud;
  ans = ksm(ans, k - 2);
  int fin =
      (ll)ans.a[1][1] * eud % mdn + (ll)ud * eud % mdn * ans.a[2][1] % mdn;
  fin %= mdn;
  int mis = ksm(cnt, k - 1); // printf("%d\n",mis);
  // printf("%d %d %d %d\n",ans.a[1][1],ans.a[1][2],ans.a[2][1],ans.a[2][2]);
  printf("%d\n", (mis - fin + mdn) % mdn);
  return 0;
}

Fixed submission:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#define inf 20021225
#define ll long long
#define mdn 1000000007
using namespace std;

struct matrix {
  int a[3][3], n;
};
inline void init(matrix &a) { memset(a.a, 0, sizeof(a.a)); }
matrix operator*(matrix a, matrix b) {
  matrix tmp;
  init(tmp);
  tmp.n = a.n;
  // printf("%d\n",tmp.a[2][2]);
  for (int i = 1; i <= a.n; i++)
    for (int j = 1; j <= a.n; j++)
      for (int k = 1; k <= a.n; k++)
        tmp.a[i][j] = ((ll)tmp.a[i][j] + (ll)a.a[i][k] * b.a[k][j] % mdn) % mdn;
  return tmp;
}

matrix ksm(matrix bs, ll mi) {
  matrix tmp;
  tmp.n = bs.n;
  init(tmp);
  for (int i = 1; i <= tmp.n; i++)
    tmp.a[i][i] = 1;
  while (mi) {
    if (mi & 1)
      tmp = tmp * bs;
    bs = bs * bs;
    mi >>= 1;
  }
  return tmp;
}
char mp[1100][1100];
int ud, lr, eud, elr, cnt;
int ksm(int bs, ll mi) {
  int ans = 1;
  while (mi) {
    if (mi & 1)
      ans = (ll)ans * bs % mdn;
    bs = (ll)bs * bs % mdn;
    mi >>= 1;
  }
  return ans;
}
int main() {
  int h, w;
  ll k;
  scanf("%d%d%lld", &h, &w, &k);
  if (k <= 1) {
    printf("1\n");
    return 0;
  }
  for (int i = 1; i <= h; i++) {
    scanf("%s", mp[i] + 1);
    if (mp[i][1] == mp[i][w] && mp[i][1] == '#')
      lr++;
    for (int j = 2; j <= w; j++)
      if (mp[i][j] == mp[i][j - 1] && mp[i][j] == '#')
        elr++;
  }
  for (int i = 2; i <= h; i++)
    for (int j = 1; j <= w; j++)
      if (mp[i - 1][j] == mp[i][j] && mp[i][j] == '#')
        eud++;
  for (int i = 1; i <= w; i++)
    if (mp[1][i] == mp[h][i] && mp[h][i] == '#')
      ud++;
  for (int i = 1; i <= h; i++)
    for (int j = 1; j <= w; j++)
      cnt += (mp[i][j] == '#');
  if (lr && ud) {
    printf("1\n");
    return 0;
  }
  if (!lr && !ud) {
    printf("%d\n", ksm(cnt, k - 1));
    return 0;
  }
  // printf("QAQ");
  if (lr)
    swap(lr, ud), swap(elr, eud); // only ud
  matrix ans;
  ans.n = 2; // printf("%d %d\n",eud,ud);
  ans.a[1][1] = cnt;
  ans.a[1][2] = 0;
  ans.a[2][1] = 1;
  ans.a[2][2] = ud;
  ans = ksm(ans, k - 2);
  int fin =
      (ll)ans.a[1][1] * eud % mdn + (ll)ud * eud % mdn * ans.a[2][1] % mdn;
  fin %= mdn;
  int mis = ksm(cnt, k - 1); // printf("%d\n",mis);
  // printf("%d %d %d %d\n",ans.a[1][1],ans.a[1][2],ans.a[2][1],ans.a[2][2]);
  printf("%d\n", (mis - fin + mdn) % mdn);
  return 0;
}