2019 ICPC國際大學生程序設計競賽中國邀請賽(南昌) H. Coloring Game

David has a white board with 2 \times N2×N grids.He decides to paint some grids black with his brush.He always starts at the top left corner and ends at the bottom right corner, where grids should be black ultimately.

Each time he can move his brush up(), down(), left(), right(), left up(), left down(), right up(), right down () to the next grid.

For a grid visited before,the color is still black. Otherwise it changes from white to black.

David wants you to compute the number of different color schemes for a given board. Two color schemes are considered different if and only if the color of at least one corresponding position is different.

Input

One line including an integer n(0<n \le 10^9)n(0<n≤109)

Output

One line including an integer, which represent the answer \bmod 1000000007mod1000000007

樣例輸入1複製

2

樣例輸出1

4

樣例解釋1

樣例輸入2

3

樣例輸出2

12

樣例解釋2

題目意思是說有一個2*N的網格,從左上角塗色,塗到右下角爲止,可以往旁邊8個方向擴散,問一共有多少種不同的塗色方案,結果對1e9+7取模

拿到這道題第一反應就是打表,試試看能不能發現某些規律

所以可以先來個暴力

#include<iostream>
#include<vector>
#include<set>
#include<cstring>
using namespace std;
const int maxn = 100;
set<vector<int> > sset;
int n;
int dir[8][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
int maze[2][maxn];
int valid(int x, int y) {
  return x >= 0 && x < 2 && y >= 0 && y < n;
}
void dfs(int x, int y) {
  vector<int> v;
  if (x == 1 && y == n - 1) {
    for (int i = 0; i < 2; i++) {
      for (int j = 0; j < n; j++) {
        v.push_back(maze[i][j]);
      }
    }
    sset.insert(v);
    return;
  }
  for (int i = 0; i < 8; i++) {
    int nx = x + dir[i][0], ny = y + dir[i][1];
    if (valid(nx, ny) && !maze[nx][ny]) {
      maze[nx][ny] = 1;
      dfs(nx, ny);
      maze[nx][ny] = 0;
    }
  }
}
int main() {
  for (n = 1; n <= 50; n++) {
    sset.clear();
    memset(maze, 0, sizeof(maze));
    maze[0][0] = 1;
    dfs(0, 0);
    cout << sset.size() << endl;
  }
  return 0;
}

每產生一種方案就往vector容器裏存,再通過set去重,然後可以發現,結果是這樣的

所以可以大膽推測,從n = 2開始,結果構成一個首項爲4,公比爲3的等比數列,所以終於可以用快速冪取模解決了

#include<iostream>
using namespace std;
const int MOD = 1e9 + 7;
long long quick_pow(int n, int k) {
  long long res = 1, base = n;
  while (k) {
    if (k & 1) res = res * base % MOD;
    base = base * base % MOD;
    k >>= 1;
  }
  return res;
}
int main() {
  int n;
  cin >> n;
  if (n == 1) cout << "1";
  else cout << 4 * quick_pow(3, n - 2) % MOD;
  return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章