#include<bits/stdc++.h>

using namespace std;

int N = 50, M = 50, mod, a[109][109];
int DBG = 0;
const int OVRL = 250;

namespace localTester {
    int s[109][109], a[109][109];
    void init (int overall)
    {
        if (DBG == 1)
        {
            memset (a, 0, sizeof (a));
            memset (s, 0, sizeof (s));
            int nr = 0, x[N * M + 1], y[N * M + 1];
            for (int i=1; i<=N; i++)
                for (int j=1; j<=M; j++)
                    x[++nr] = i, y[nr] = j;
            bool type[nr + 1];
            for (int i=1; i<=nr; i++)
                type[i] = (i <= overall);
            random_shuffle (type + 1, type + nr + 1);
            for (int i=1; i<=nr; i++)
                if (type[i])
                    a[x[i]][y[i]] = s[x[i]][y[i]] = 1;
        }
        else
        if (DBG == 2)
        {
            for (int i=1; i<=N; i++)
                for (int j=1; j<=M; j++)
                    scanf ("%d", &a[i][j]), s[i][j] = a[i][j];
        }
        for (int i=1; i<=N; i++)
            for (int j=1; j<=M; j++)
                s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
    }
    int query (int a1, int b1, int a2, int b2)
    {
        return s[a2][b2] - s[a1 - 1][b2] - s[a2][b1 - 1] + s[a1 - 1][b1 - 1];
    }
}

int queries = 0;
int query (int a1, int b1, int a2, int b2)
{
    queries ++;
    if (DBG) return localTester::query (a1, b1, a2, b2);
    printf ("? %d %d %d %d\n", a1 - 1, b1 - 1, a2 - 1, b2 - 1);
    fflush (stdout);
    int x;
    scanf ("%d", &x);
    return x;
}

//int lg[109];
int lg[]={0,1,1,2,2,4,4,4,4,8,8,8,4,5,2,4,4,5,8,11,14,11,6,7,16,13,10,15,24,1,16,8,16,1,2,3,28,1,22,7,8,10,36,8,6,29,22,24,8,18,18};
int getMid (int a, int b, int currH)
{
    if (currH == 0)
    {
        if (rand () & 1)
            return a + lg[b - a + 1] - 1;
        else
            return b - lg[b - a + 1];
    }
    if (rand () & 1)
        return a + currH - 1;
    else
        return b - currH;
//    return a + rand () % (b - a + 1);
}

const int K = 30;
int how[K + 1][K + 1][K * K + 1];
void solve (int a1, int b1, int a2, int b2, int sum)
{
    if (sum == 0 || sum == (a2 - a1 + 1) * (b2 - b1 + 1))
    {
        for (int i=a1; i<=a2; i++)
            for (int j=b1; j<=b2; j++)
                a[i][j] = (sum > 0);
        return ;
    }
    int currH = 0;
    if (a2 - a1 + 1 <= K && b2 - b1 + 1 <= K)
        currH = how[a2 - a1 + 1][b2 - b1 + 1][sum];
    if ((a2 - a1 < b2 - b1 && currH == 0) || currH < 0)
    {
        int mid = getMid (b1, b2, -currH), s0 = query (a1, b1, a2, mid);
        solve (a1, b1, a2, mid, s0);
        solve (a1, mid + 1, a2, b2, sum - s0);
    }
    else
    {
        int mid = getMid (a1, a2, currH), s0 = query (a1, b1, mid, b2);
        solve (a1, b1, mid, b2, s0);
        solve (mid + 1, b1, a2, b2, sum - s0);
    }
}

void finish ()
{
    if (DBG)
    {
        for (int i=1; i<=N; i++)
            for (int j=1; j<=M; j++)
                if (localTester::a[i][j] != a[i][j])
                {
                    printf ("WA\n");
                    exit (0);
                }
        printf ("OK %d\n", queries);
        //exit (0);
    }
    int p2[N * M + 10], ans = 0;
    p2[0] = 1;
    for (int i=1; i<=N * M; i++)
        p2[i] = (p2[i - 1] + p2[i - 1]) % mod;
    for (int i=0; i<N; i++)
        for (int j=0; j<M; j++)
            if (a[i + 1][j + 1])
                ans = (ans + p2[i * M + j]) % mod;
    printf ("! %d\n", ans);
/*    for (int i=1; i<=N; i++, printf ("\n"))
        for (int j=1; j<=M; j++)
            printf ("%d", a[i][j]);*/
    fflush (stdout);
}

double averageTrying (int overall)
{
    int steps = 1000;
    double sum = 0;
    while (steps --)
    {
        localTester::init (overall), queries = 0;
        solve (1, 1, N, M, overall), sum += queries;
    }
    sum /= 1000.0;
    return sum;
}

//double dp[109];
double dp[K + 1][K + 1][K * K + 1], c[2509][259];
int main ()
{
//freopen ("input", "r", stdin);
//freopen ("output", "w", stdout);

srand (time (0));
c[0][0] = 1.0;
for (int i=1; i<=2500; i++)
    for (int j=0; j<250 && j<=i; j++)
    {
        c[i][j] = (j == 0 ? 0 : c[i - 1][j - 1]) + c[i - 1][j];
        c[i][j] /= 2.0;
    }
double steps = 0.0;
for (int i=1; i<=K; i++)
    for (int j=1; j<=K; j++)
    {
        for (int k=0; k<=i * j && k <= OVRL; k++)
        {
            if (k == 0 || k == i * j)
            {
                dp[i][j][k] = 0;
                continue;
            }
            dp[i][j][k] = 1e9;
            for (int l=1; l<i; l++)
            {
                double worst = 0;
                for (int k0=max (k - (i - l) * j, 0); k0<=k && k0<=l * j; k0++)
                {
                    int k1 = k - k0;
                    double curr = dp[l][j][k0] + dp[i - l][j][k1] + 1;
                    double P = 1.0 * c[l * j][k0] * c[(i - l) * j][k1];
                    worst += 1.0 * curr * P;
                }
                if (worst < dp[i][j][k])
                    dp[i][j][k] = worst, how[i][j][k] = l;
            }
            for (int l=1; l<j; l++)
            {
                double worst = 0;
                for (int k0=max (k - (j - l) * i, 0); k0<=k && k0 <= i * l; k0++)
                {
                    int k1 = k - k0;
                    double curr = dp[i][l][k0] + dp[i][j - l][k1] + 1;
                    double P = 1.0 * c[l * i][k0] * c[(j - l) * i][k1];
                    worst += 1.0 * curr * P;
                }
                if (worst < dp[i][j][k])
                    dp[i][j][k] = worst, how[i][j][k] = -l;
            }
            dp[i][j][k] /= c[i * j][k];
        }
        steps += 1.0 / (K * K);
//        printf ("%.2f done\n", 100.0 * steps);
    }
if (N <= K && M <= K && OVRL <= K * K)
    printf ("%.10f\n", dp[N][M][OVRL]);
//return 0;
/*int j = 1;
for (int i=1; i<=2; i++)
{
    while (2 * j < i)
        j += j;
    lg[i] = j;
}
for (int L=3; L<=50; L++)
{
    int how = -1;
    dp[L] = 10000000.0;
    for (int i=1; i<L; i++)
    {
        lg[L] = i, N = M = L;
        double curr = averageTrying (L * L / 10);
        if (curr < dp[L])
            dp[L] = curr, how = i;
    }
    lg[L] = how;
}
printf ("%.10f\n", dp[50]);
printf ("lg={0");
for (int i=1; i<=50; i++)
    printf (",%d", lg[i]);
printf ("};\n");
return 0;*/
if (DBG > 0)
{
    //lg[50] = 40, lg[40] = 30, lg[30] = 20, lg[20] = 10;
    printf ("%.5f\n", averageTrying (OVRL));
    return 0;
}
int overall;
scanf ("%d %d %d %d", &N, &M, &overall, &mod);
localTester::init (overall);
solve (1, 1, N, M, overall);
finish ();

return 0;
}


Measured memory_bytes: 15956