8cbd8685a8 2019-07-19 kinaba: #include <iostream> 8cbd8685a8 2019-07-19 kinaba: #include <sstream> 8cbd8685a8 2019-07-19 kinaba: #include <iomanip> 8cbd8685a8 2019-07-19 kinaba: #include <vector> 8cbd8685a8 2019-07-19 kinaba: #include <string> 8cbd8685a8 2019-07-19 kinaba: #include <map> 8cbd8685a8 2019-07-19 kinaba: #include <set> 8cbd8685a8 2019-07-19 kinaba: #include <algorithm> 8cbd8685a8 2019-07-19 kinaba: #include <numeric> 8cbd8685a8 2019-07-19 kinaba: #include <iterator> 8cbd8685a8 2019-07-19 kinaba: #include <functional> 8cbd8685a8 2019-07-19 kinaba: #include <complex> 8cbd8685a8 2019-07-19 kinaba: #include <queue> 8cbd8685a8 2019-07-19 kinaba: #include <stack> 8cbd8685a8 2019-07-19 kinaba: #include <cmath> 8cbd8685a8 2019-07-19 kinaba: #include <cassert> 8cbd8685a8 2019-07-19 kinaba: #include <tuple> 8cbd8685a8 2019-07-19 kinaba: using namespace std; 8cbd8685a8 2019-07-19 kinaba: typedef long long LL; 8cbd8685a8 2019-07-19 kinaba: typedef complex<double> CMP; 8cbd8685a8 2019-07-19 kinaba: 8cbd8685a8 2019-07-19 kinaba: static const unsigned MODVAL = 1000000007; 8cbd8685a8 2019-07-19 kinaba: struct mint 8cbd8685a8 2019-07-19 kinaba: { 8cbd8685a8 2019-07-19 kinaba: unsigned val; 8cbd8685a8 2019-07-19 kinaba: mint() :val(0) {} 8cbd8685a8 2019-07-19 kinaba: mint(int x) :val(x%MODVAL) {} 8cbd8685a8 2019-07-19 kinaba: mint(unsigned x) :val(x%MODVAL) {} 8cbd8685a8 2019-07-19 kinaba: mint(LL x) :val(x%MODVAL) {} 8cbd8685a8 2019-07-19 kinaba: }; 8cbd8685a8 2019-07-19 kinaba: mint& operator+=(mint& x, mint y) { return x = x.val + y.val; } 8cbd8685a8 2019-07-19 kinaba: mint& operator-=(mint& x, mint y) { return x = x.val - y.val + MODVAL; } 8cbd8685a8 2019-07-19 kinaba: mint& operator*=(mint& x, mint y) { return x = LL(x.val)*y.val; } 8cbd8685a8 2019-07-19 kinaba: mint operator+(mint x, mint y) { return x += y; } 8cbd8685a8 2019-07-19 kinaba: mint operator-(mint x, mint y) { return x -= y; } 8cbd8685a8 2019-07-19 kinaba: mint operator*(mint x, mint y) { return x *= y; } 8cbd8685a8 2019-07-19 kinaba: mint POW(mint x, LL e) { mint v = 1; for (; e; x *= x, e >>= 1) if (e & 1) v *= x; return v; } 8cbd8685a8 2019-07-19 kinaba: mint& operator/=(mint& x, mint y) { return x *= POW(y, MODVAL - 2); } 8cbd8685a8 2019-07-19 kinaba: mint operator/(mint x, mint y) { return x /= y; } 8cbd8685a8 2019-07-19 kinaba: 8cbd8685a8 2019-07-19 kinaba: class DiagonalColumn { public: 8cbd8685a8 2019-07-19 kinaba: int countGrids(int H, int W) 8cbd8685a8 2019-07-19 kinaba: { 8cbd8685a8 2019-07-19 kinaba: mint ans = 1; // all black 8cbd8685a8 2019-07-19 kinaba: for(int l=0; l<W; ++l) 8cbd8685a8 2019-07-19 kinaba: for (int r = 0; l + r < W; ++r) { 8cbd8685a8 2019-07-19 kinaba: if (W - l - r <= 2) 8cbd8685a8 2019-07-19 kinaba: ans += 1; 8cbd8685a8 2019-07-19 kinaba: else 8cbd8685a8 2019-07-19 kinaba: ans += sub(H, W - l - r); 8cbd8685a8 2019-07-19 kinaba: } 8cbd8685a8 2019-07-19 kinaba: return ans.val; 8cbd8685a8 2019-07-19 kinaba: } 8cbd8685a8 2019-07-19 kinaba: 8cbd8685a8 2019-07-19 kinaba: mint sub(LL H, LL W) 8cbd8685a8 2019-07-19 kinaba: { 8cbd8685a8 2019-07-19 kinaba: // columns = _?????_ 8cbd8685a8 2019-07-19 kinaba: mint f = POW(2, W - 2); 8cbd8685a8 2019-07-19 kinaba: 8cbd8685a8 2019-07-19 kinaba: // Diag: H+W-1個のうち 8cbd8685a8 2019-07-19 kinaba: // 最初H個のどれかはmust空き 8cbd8685a8 2019-07-19 kinaba: // 最後H個のどれかはmust空き 8cbd8685a8 2019-07-19 kinaba: // 他でH連続塗りがある場合は縦の自由度が減る /2 8cbd8685a8 2019-07-19 kinaba: vector<mint> dp(H+1); 8cbd8685a8 2019-07-19 kinaba: dp[0] = f; 8cbd8685a8 2019-07-19 kinaba: for (int i = 0; i < H + W - 1; ++i) { 8cbd8685a8 2019-07-19 kinaba: vector<mint> dp_prev = dp; 8cbd8685a8 2019-07-19 kinaba: vector<mint> dp(H+1); 8cbd8685a8 2019-07-19 kinaba: for (int r = 0; r <= H; ++r) { 8cbd8685a8 2019-07-19 kinaba: if (r == 0) { 8cbd8685a8 2019-07-19 kinaba: accumulate(dp_prev.begin(), dp_prev.end(), mint(0)); 8cbd8685a8 2019-07-19 kinaba: } 8cbd8685a8 2019-07-19 kinaba: else { 8cbd8685a8 2019-07-19 kinaba: if(r == H) 8cbd8685a8 2019-07-19 kinaba: dp[r] = (i == H - 1 || i == H + W - 2 ? mint(0) : (dp_prev[r - 1]+ dp_prev[r]) / 2); 8cbd8685a8 2019-07-19 kinaba: else 8cbd8685a8 2019-07-19 kinaba: dp[r] = dp_prev[r - 1]; 8cbd8685a8 2019-07-19 kinaba: } 8cbd8685a8 2019-07-19 kinaba: } 8cbd8685a8 2019-07-19 kinaba: } 8cbd8685a8 2019-07-19 kinaba: return accumulate(dp.begin(), dp.begin() + H, mint(0)); 8cbd8685a8 2019-07-19 kinaba: } 8cbd8685a8 2019-07-19 kinaba: }; 8cbd8685a8 2019-07-19 kinaba: 8cbd8685a8 2019-07-19 kinaba: // BEGIN CUT HERE 8cbd8685a8 2019-07-19 kinaba: #include <ctime> 8cbd8685a8 2019-07-19 kinaba: double start_time; string timer() 8cbd8685a8 2019-07-19 kinaba: { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } 8cbd8685a8 2019-07-19 kinaba: template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) 8cbd8685a8 2019-07-19 kinaba: { os << "{ "; 8cbd8685a8 2019-07-19 kinaba: for(typename vector<T>::const_iterator it=v.begin(); it!=v.end(); ++it) 8cbd8685a8 2019-07-19 kinaba: os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return os; } 8cbd8685a8 2019-07-19 kinaba: void verify_case(const int& Expected, const int& Received) { 8cbd8685a8 2019-07-19 kinaba: bool ok = (Expected == Received); 8cbd8685a8 2019-07-19 kinaba: if(ok) cerr << "PASSED" << timer() << endl; else { cerr << "FAILED" << timer() << endl; 8cbd8685a8 2019-07-19 kinaba: cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } } 8cbd8685a8 2019-07-19 kinaba: #define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock(); 8cbd8685a8 2019-07-19 kinaba: #define END verify_case(_, DiagonalColumn().countGrids(H, W));} 8cbd8685a8 2019-07-19 kinaba: int main(){ 8cbd8685a8 2019-07-19 kinaba: 8cbd8685a8 2019-07-19 kinaba: CASE(0) 8cbd8685a8 2019-07-19 kinaba: int H = 2; 8cbd8685a8 2019-07-19 kinaba: int W = 2; 8cbd8685a8 2019-07-19 kinaba: int _ = 12; 8cbd8685a8 2019-07-19 kinaba: END 8cbd8685a8 2019-07-19 kinaba: CASE(1) 8cbd8685a8 2019-07-19 kinaba: int H = 2; 8cbd8685a8 2019-07-19 kinaba: int W = 3; 8cbd8685a8 2019-07-19 kinaba: int _ = 37; 8cbd8685a8 2019-07-19 kinaba: END 8cbd8685a8 2019-07-19 kinaba: CASE(2) 8cbd8685a8 2019-07-19 kinaba: int H = 3; 8cbd8685a8 2019-07-19 kinaba: int W = 2; 8cbd8685a8 2019-07-19 kinaba: int _ = 28; 8cbd8685a8 2019-07-19 kinaba: END 8cbd8685a8 2019-07-19 kinaba: CASE(3) 8cbd8685a8 2019-07-19 kinaba: int H = 1; 8cbd8685a8 2019-07-19 kinaba: int W = 5; 8cbd8685a8 2019-07-19 kinaba: int _ = 32; 8cbd8685a8 2019-07-19 kinaba: END 8cbd8685a8 2019-07-19 kinaba: CASE(4) 8cbd8685a8 2019-07-19 kinaba: int H = 6; 8cbd8685a8 2019-07-19 kinaba: int W = 1; 8cbd8685a8 2019-07-19 kinaba: int _ = 64; 8cbd8685a8 2019-07-19 kinaba: END 8cbd8685a8 2019-07-19 kinaba: CASE(5) 8cbd8685a8 2019-07-19 kinaba: int H = 38; 8cbd8685a8 2019-07-19 kinaba: int W = 38; 8cbd8685a8 2019-07-19 kinaba: int _ = 173889321; 8cbd8685a8 2019-07-19 kinaba: END 8cbd8685a8 2019-07-19 kinaba: /* 8cbd8685a8 2019-07-19 kinaba: CASE(6) 8cbd8685a8 2019-07-19 kinaba: int H = ; 8cbd8685a8 2019-07-19 kinaba: int W = ; 8cbd8685a8 2019-07-19 kinaba: int _ = ; 8cbd8685a8 2019-07-19 kinaba: END 8cbd8685a8 2019-07-19 kinaba: CASE(7) 8cbd8685a8 2019-07-19 kinaba: int H = ; 8cbd8685a8 2019-07-19 kinaba: int W = ; 8cbd8685a8 2019-07-19 kinaba: int _ = ; 8cbd8685a8 2019-07-19 kinaba: END 8cbd8685a8 2019-07-19 kinaba: */ 8cbd8685a8 2019-07-19 kinaba: } 8cbd8685a8 2019-07-19 kinaba: // END CUT HERE