Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <string>
- #include <set>
- #include <unordered_set>
- #include <map>
- #include <algorithm>
- #include <math.h>
- #include <queue>
- #include <stack>
- #include <time.h>
- #include <memory.h>
- using namespace std;
- typedef long long LL;
- typedef pair<int, int> PII;
- typedef vector<int> VI;
- typedef pair<double, double> PDD;
- const double PI = acos(-1.0);
- #define FOR(i,a,b) for(int i=(a);i<(b);i++)
- #define RFOR(i,a,b) for(int i=(a)-1;i>=0;i--)
- #define PB push_back
- #define MP make_pair
- #define SZ(a) (int)a.size()
- #define ALL(a) (a.begin(),a.end())
- #define FILL(a, x) memset(a, x, sizeof(a));
- const int MAX = 22;
- int n, m, x, MOD;
- map<int,int> DP[22][22][200];
- string S[22];
- bool A[22][22];
- bool hasBit(int mask, int i) {
- return mask&(1 << i);
- }
- void setBit(int& mask, int i) {
- mask |= (1 << i);
- }
- void ADD(int& to, int x) {
- to += x;
- while (to >= MOD)to -= MOD;
- }
- void solve() {
- DP[0][0][0][0] = 1;
- FOR(i, 0, n)
- FOR(j, 0, m)
- FOR(k, 0, x + 1) {
- for (map<int,int>::iterator it = DP[i][j][k].begin(); it != DP[i][j][k].end(); ++it)
- {
- int val = it->second;
- if (!val)continue;
- int msk = it->first;
- // cerr << i << " " << j << " " << k << " " <<" "<<msk<<" "<< val << endl;
- int nI = i;
- int nJ = j + 1;
- if (nJ == m) {
- nI++;
- nJ = 0;
- }
- bool canJoinUp = (i > 0 && !hasBit(msk, j));
- if (canJoinUp) {
- bool plus1 = A[i - 1][j] == true && A[i][j] == true;
- int nk = k + plus1;
- if (nk<=x) {
- int nmask = msk;
- setBit(nmask, j);
- map<int, int>::iterator w = DP[nI][nJ][nk].find(nmask);
- if (w == DP[nI][nJ][nk].end()) {
- DP[nI][nJ][nk][nmask] = val;
- }
- else {
- ADD(w->second, val);
- }
- }
- continue;
- }
- bool canJoinLeft = (j > 0 && !hasBit(msk, j - 1));
- if (canJoinLeft) {
- bool plus1 = A[i][j - 1] == true && A[i][j] == true;
- int nk = k + plus1;
- if (nk<=x) {
- int nmask = msk;
- setBit(nmask, j);
- setBit(nmask, j - 1);
- // if(DP[nI][nJ][k + plus1].count(n)
- map<int, int>::iterator w = DP[nI][nJ][nk].find(nmask);
- if (w == DP[nI][nJ][nk].end()) {
- DP[nI][nJ][nk][nmask] = val;
- }
- else {
- ADD(w->second, val);
- }
- }
- }
- bool canSkip = true;//i == 0 || hasBit(msk, j);
- if (canSkip) {
- int nmask = msk;
- if (hasBit(nmask, j)) {
- nmask ^= 1 << j;
- }
- map<int, int>::iterator w = DP[nI][nJ][k].find(nmask);
- if (w == DP[nI][nJ][k].end()) {
- DP[nI][nJ][k][nmask] = val;
- }
- else {
- ADD(w->second, val);
- }
- }
- }
- }
- }
- int main()
- {
- //ios::sync_with_stdio(0); cin.tie(0);
- string name = "08";
- freopen(("C:\\Users\\felix\\Desktop\\sets\\division"+name+".in").c_str(), "r", stdin);
- freopen(("C:\\Users\\felix\\Desktop\\sets\\division\\division" + name + ".ans").c_str(), "w", stdout);
- // freopen("in.txt", "r", stdin);
- //C:\Users\felix\Desktop\sets
- int T;
- cin >> T;
- while (T--) {
- cin >> m >> n >> x >> MOD;
- cerr << T << endl;
- FOR(i, 0, n) {
- cin >> S[i];
- }
- if ((n*m) % 2 == 1) {
- cout << 0 << endl;
- continue;
- }
- if (m > n) {
- FOR(i,0,n)
- FOR(j, 0, m) {
- A[j][i] = S[i][j] == 'A';
- }
- swap(n, m);
- }
- else {
- FOR(i, 0, n)
- FOR(j, 0, m)
- A[i][j] = S[i][j] == 'A';
- }
- FOR(i, 0, n + 1)
- FOR(j,0,m)
- FOR(k,0,x+1){
- DP[i][j][k].clear();
- }
- solve();
- int mm = (1 << m) - 1;
- int ans = 0;
- if (DP[n][0][x].count(mm)) {
- ans = DP[n][0][x][mm];
- }
- cout << ans << "\n";
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement