Submission #49988

#TimeUsernameProblemLanguageResultExecution timeMemory
49988shoemakerjoTents (JOI18_tents)C++14
100 / 100
276 ms142040 KiB
#include <bits/stdc++.h> using namespace std; #define maxd 3005 #define ll long long const int mod = 1000000007; int H, W; ll nomore[maxd][maxd]; //using ll just in case ll rorem[maxd]; ll colrem[maxd][maxd]; ll facts[maxd]; ll invfacts[maxd]; ll modpow(ll base, ll pc) { if (pc == 0) return 1LL; if (pc & 1) { ll tmp = modpow(base, pc-1LL); return (tmp * base) % mod; } ll tmp = modpow(base, pc/2LL); return (tmp*tmp)%mod; } ll inv(ll cur) { return modpow(cur, mod-2); } void dofacts() { //calculate factorials and their inverses facts[0] = 1LL; invfacts[0] = 1LL; for (int i = 1; i < maxd; i++) { facts[i] = (facts[i-1]*1LL*i)%mod; invfacts[i] = inv(facts[i]); } } ll choose(int a, int b) { //return a combination b ll ans = facts[a] * (invfacts[a-b] * invfacts[b] % mod) % mod; return ans % mod; // just in case } void calcnomore() { //do if we do no more pairing up //f(x, 0) = f(0, x) = 1 //f(x, y) = f(x, y-1) + 4*x*f(x-1, y-1) for (int i = 0; i <= max(H, W); i++) { nomore[0][i] = nomore[i][0] = 1LL; } for (int i = 1; i <= H; i++) { for (int j = 1; j <= W; j++) { nomore[i][j] = nomore[i][j-1] + 0LL + 4LL * i * nomore[i-1][j-1] % mod; nomore[i][j] %= mod; } } } void calcrorem() { //calculate how many ways you can do x row removals for (int i = 0; i <= H; i++) { rorem[i] = 0LL; //incase we break } ll runprod = 1LL; //the running product rorem[0] = 1LL; //only one way to remove nothing for (int i = 1; i <= H; i++) { if (2*i > W) break; //cannot take all of this runprod = (runprod * choose(W - i*2 + 2, 2))%mod; ll cur = (runprod * choose(H, i))%mod; rorem[i] = cur; } } void calccolrem() { //calc how many ways you can do y column removals, // given you already did x row removals for (int i = 0; i <= H; i++) { for (int j = 0; j <= W; j++) { colrem[i][j] = 0LL; //same idea, set to zero in case we break } } for (int i = 0; i <= H; i++) { if (2*i > W) break; int h = H-i; int w = W - 2*i; //little h and w represent slightly changed values ll runprod = 1LL; colrem[i][0] = 1LL; //one way to remove nothing for (int j = 1; j <= W; j++) { if (2*i + j > W || i + 2*j > H) break; //something is deficient runprod = (runprod * choose(h - j*2 + 2, 2))%mod; ll cur =(runprod * choose(w, j))%mod; colrem[i][j] = cur; } } } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); cin >> H >> W; dofacts(); calcnomore(); calcrorem(); calccolrem(); ll ans = 0LL; //looking at doing x row rem and y col rem for (int i = 0; i <= H; i++) { for (int j = 0; j <= W; j++) { ll cur = (rorem[i] * colrem[i][j]) % mod; if (cur == 0LL) continue; //do not get index out of bounds cur = (cur * nomore[H - i - 2*j][W - 2*i - j]) % mod; // cout << i << " " << j << ": " << cur << endl; ans = (ans + cur) % mod; } } // cout << "ans: "; ans = (ans + mod - 1LL)%mod; //subtract out the nothing placed case cout << ans << endl; cin >> ans; } //probably some dp
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...