You are viewing a single comment's thread. Return to all comments →
c++
#include <cstdio> #include <cstring> #include <cmath> #include <cassert> #include <ctime> #include <set> #include <map> #include <vector> #include <string> #include <sstream> #include <numeric> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; typedef pair<int, int> PII; typedef pair<PII, int> PI3; typedef pair<PI3, vector<int> > PIV; #define fi first #define se second #define mp make_pair #define pb push_back #define mp3(x, y, z) mp(mp(x, y), z) #define fi3 fi.fi #define se3 fi.se #define th3 se #define pct __builtin_popcount #define ctz __builtin_ctz #define P 1000000007 #define N 1010 int n, m, p, S0, wn; vector<PII> w; int px[N], py[N], qx[N], qy[N]; int sx[N], sy[N]; int p0[N]; int mn, mm; bool cmpx(int x, int y) { return sx[x] > sx[y]; } bool cmpy(int x, int y) { return sy[x] > sy[y]; } int F0[2010][1010]; map<PIV, int> F1; int rem(int x, int w) { return (x >> w+1 << w) + (x & ((1 << w)-1)); } int rem(int x, int w1, int w2) { if (w1 > w2) swap(w1, w2); return rem(rem(x, w1), w2-1); } int gg(int n, int m, vector<int> a, int r) { if (r < 0 || r > n || r > m) return 0; if (r == 0 || n == 0 || m == 0) return 1; PIV wp = mp(mp3(n, m, r), a); if (F1.find(wp) != F1.end()) return F1[wp]; int &S = F1[wp]; for (int j = 2; j >= 0; j --) { for (int i = n-1; i >= 0; i --) if (pct(a[i]) <= j || pct(a[i]) >= m-j) { swap(a[i], a[n-1]); break; } } int pc = pct(a[n-1]); if (pc == m) { vector<int> a1; for (int i = 0; i < n-1; i ++) a1.pb(a[i]); S = gg(n-1, m, a1, r); } else if (pc == 0) { vector<int> a1; for (int i = 0; i < n-1; i ++) a1.pb(a[i]); int S1 = gg(n-1, m, a1, r); int S2 = gg(n-1, m, a1, r-1); (S += (ll)p0[r]*S1%P) %= P; (S += (ll)(p0[m]-p0[r-1]+P)%P*S2%P) %= P; } else if (pc == m-1) { vector<int> a1; for (int i = 0; i < n-1; i ++) a1.pb(a[i]); (S += gg(n-1, m, a1, r)) %= P; int inva = (1 << m) - 1 - a[n-1]; int w = ctz(inva), s = 0; for (int i = 0; i < n-1; i ++) { if (~(a1[i] >> w)&1) s ++; a1[i] = rem(a1[i], w); } (S += (ll)(p-1)*p0[s]%P*gg(n-1, m-1, a1, r-1)%P) %= P; } else if (pc == 1) { vector<int> a1, a2; for (int i = 0; i < n-1; i ++) a1.pb(a[i]); int w = ctz(a[n-1]); for (int i = 0; i < n-1; i ++) a2.pb(rem(a[i], w)); int S1 = gg(n-1, m-1, a2, r); int S2 = gg(n-1, m-1, a2, r-1); int S3 = (gg(n-1, m, a1, r)-S1+P)%P; int S4 = (gg(n-1, m, a1, r-1)-S2+P)%P; (S += (ll)p0[r]*S1%P) %= P; (S += (ll)(p0[m-1]-p0[r-1]+P)%P*S2%P) %= P; (S += (ll)p0[r-1]*S3%P) %= P; if (r >= 2) (S += (ll)(p0[m-1]-p0[r-2]+P)%P*S4%P) %= P; } else if (pc == m-2) { vector<int> a1; for (int i = 0; i < n-1; i ++) a1.pb(a[i]); (S += gg(n-1, m, a1, r)) %= P; int inva = (1 << m) - 1 - a[n-1]; int w1 = ctz(inva), w2 = ctz(inva^(1 << w1)); int s1 = 0, s2 = 0; for (int i = 0; i < n-1; i ++) { if (~(a[i] >> w1) & 1) s1 ++; if (~(a[i] >> w2) & 1) s2 ++; } for (int i = 0; i < n-1; i ++) a1[i] = rem(a[i], w1); (S += (ll)(p-1)*p0[s1]%P*gg(n-1, m-1, a1, r-1)%P) %= P; for (int i = 0; i < n-1; i ++) a1[i] = rem(a[i], w2); (S += (ll)(p-1)*p0[s2]%P*gg(n-1, m-1, a1, r-1)%P) %= P; int s3 = 0; vector<int> a2; for (int i = 0; i < n-1; i ++) { if ((~(a[i] >> w1) & 1) && (~(a[i] >> w2) &1)) s3 ++; int x = a[i]; if (~(x >> w1)&1) if ((x >> w2) & 1) x ^= (1 << w2); a2.pb(rem(x, w1)); } (S += (ll)(p-1)*(p-1)%P*p0[s3]%P*gg(n-1, m-1, a2, r-1)%P) %= P; } else if (pc == 2) { int w1 = ctz(a[n-1]), w2 = ctz(a[n-1] ^ (1 << w1)); vector<int> a0, a1, a2, a3, a4; for (int i = 0; i < n-1; i ++) a0.pb(rem(a[i], w1, w2)); int S1 = gg(n-1, m-2, a0, r); int S2 = gg(n-1, m-2, a0, r-1); (S += (ll)p0[r]*S1%P) %= P; (S += (ll)(p0[m-2]-p0[r-1]+P)%P*S2%P) %= P; for (int i = 0; i < n-1; i ++) { a1.pb(rem(a[i], w1)); a2.pb(rem(a[i], w2)); } int S3 = (gg(n-1, m-1, a1, r)-S1+P)%P; int S4 = (gg(n-1, m-1, a1, r-1)-S2+P)%P; int S5 = (gg(n-1, m-1, a2, r)-S1+P)%P; int S6 = (gg(n-1, m-1, a2, r-1)-S2+P)%P; (S += (ll)p0[r-1]*S3%P) %= P; if (r >= 2) (S += (ll)(p0[m-2]-p0[r-2]+P)%P*S4%P) %= P; (S += (ll)p0[r-1]*S5%P) %= P; if (r >= 2) (S += (ll)(p0[m-2]-p0[r-2]+P)%P*S6%P) %= P; for (int i = 0; i < n-1; i ++) { int x = a[i]; if ((x >> w1) &1) x |= (1 << w2); a3.pb(rem(x, w1)); } int S7 = (ll)(p-1)*(gg(n-1, m-1, a3, r)-S1+P)%P; int S8 = (ll)(p-1)*(gg(n-1, m-1, a3, r-1)-S2+P)%P; (S += (ll)p0[r-1]*S7%P) %= P; if (r >= 2)(S += (ll)(p0[m-2]-p0[r-2]+P)%P*S8%P) %= P; for (int i = 0; i < n-1; i ++) a4.pb(a[i]); int S9 = (gg(n-1, m, a4, r)-((ll)S1+S3+S5+S7)%P+P)%P; int S10 = (gg(n-1, m, a4, r-1)-((ll)S2+S4+S6+S8)%P+P)%P; if (r >= 2) (S += (ll)p0[r-2]*S9%P) %= P; if (r >= 3) (S += (ll)(p0[m-2]-p0[r-3]+P)%P*S10%P) %= P; } else { vector<int> b; for (int i = 0; i < m; i ++) b.pb(0); for (int i = 0; i < n; i ++) for (int j = 0; j < m; j ++) if ((a[i] >> j)&1) b[j] |= (1 << i); S = gg(m, n, b, r); } return S; } int ff(int n, int m, int r) { if (r < 0 || r > n || r > m) return 0; if (r == 0 || n == 0 || m == 0) return 1; if (F0[n+m][r] != -1) return F0[n+m][r]; int &S = F0[n+m][r] = 0; if (n > mn) { (S += (ll)p0[r]*ff(n-1, m, r)%P) %= P; (S += (ll)(p0[m]-p0[r-1]+P)%P*ff(n-1, m, r-1)%P) %= P; } else if (m > mm) { (S += (ll)p0[r]*ff(n, m-1, r)%P) %= P; (S += (ll)(p0[n]-p0[r-1]+P)%P*ff(n, m-1, r-1)%P) %= P; } else { vector<int> a; for (int i = 0; i < n; i ++) a.pb(0); for (int i = 0; i < wn; i ++) a[w[i].fi] |= (1 << w[i].se); S = gg(n, m, a, r); } return S; } void solve() { static int _ = 0; _ ++; memset(F0, -1, sizeof F0); F1.clear(); p0[0] = 1; for (int i = 1; i < N; i ++) p0[i] = (ll)p0[i-1]*p%P; memset(sx, 0, sizeof sx); memset(sy, 0, sizeof sy); w.clear(); for (int i = 0; i < wn; i ++) { int x, y; scanf("%d%d", &x, &y); --x, --y; w.pb(mp(x, y)); sx[x] ++; sy[y] ++; } for (int i = 0; i < n; i ++) px[i] = i; for (int i = 0; i < m; i ++) py[i] = i; sort(px, px+n, cmpx); sort(py, py+m, cmpy); for (int i = 0; i < n; i ++) qx[px[i]] = i; for (int i = 0; i < m; i ++) qy[py[i]] = i; for (int i = 0; i < wn; i ++) w[i] = mp(qx[w[i].fi], qy[w[i].se]); for (int i = 0; i < wn; i ++) { mn = max(mn, w[i].fi + 1); mm = max(mm, w[i].se + 1); } int S = 0; for (int i = 0; i <= min(n, m); i ++) if (S0 == 0) { (S += (ll)(p0[n]-p0[i]+P)%P*ff(n, m, i)%P) %= P; } else if (p0[m-i] == S0) { (S += (ll)p0[i]*ff(n, m, i)%P) %= P; } printf ("Case #%d: %d\n", _, S); } int main() { int _ = 0; int test; scanf("%d", &test); while (scanf("%d%d%d%d%d", &n, &m, &p, &S0, &wn) != EOF) { solve(); } return 0; }
Seems like cookies are disabled on this browser, please enable them to open this website
Counting Equations
You are viewing a single comment's thread. Return to all comments →
c++