#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cassert>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
 
#define For(i, l, r) for (i = int(l); i <= int(r); i++)
#define Fo(i, n) For(i, 1, n)
#define Rof(i, r, l) for (i = int(r); i >= int(l); i--)
#define Ro(i, n) Rof(i, n, 1)
#define clr(a) memset(a, 0, sizeof(a))
#define cpy(a, b) memcpy(a, b, sizeof(b))
#define fc(a, ch) memset(a, ch, sizeof(a))
 
typedef unsigned long long uint64;
typedef long long int64;
 
#define T1 template <class A>
#define T2 template <class A, class B>
#define T3 template <class A, class B, class C>
#define T4 template <class A, class B, class C, class D>
inline void read(char &x) {
    do
        x = getchar();
    while (x <= ' ');
}
inline void read(char *s) {
    char ch;
 
    do
        ch = getchar();
    while (ch <= ' ');
    while (ch > ' ') {
        (*s) = ch;
        s++;
        ch = getchar();
    }
    (*s) = 0;
}
inline void read(std::string &s) {
    char ch;
 
    do
        ch = getchar();
    while (ch <= ' ');
    while (ch > ' ') {
        s.push_back(ch);
        ch = getchar();
    }
}
T1 inline void readint(A &x) {
    bool neg = false;
    char ch;
 
    do
        ch = getchar();
    while (ch <= ' ');
    if (ch == '-') {
        neg = true;
        ch = getchar();
    }
    x = 0;
    while (ch > ' ') {
        x = x * 10 + (ch & 15);
        ch = getchar();
    }
    if (neg)
        x = -x;
}
inline void read(int &x) { readint(x); }
inline void read(int64 &x) { readint(x); }
 
T2 inline void read(A &a, B &b) {
    read(a);
    read(b);
}
T3 inline void read(A &a, B &b, C &c) {
    read(a);
    read(b);
    read(c);
}
T4 inline void read(A &a, B &b, C &c, D &d) {
    read(a);
    read(b);
    read(c);
    read(d);
}
inline void writeln() { putchar('\n'); }
T1 inline void writeint(A x) {
    static char buf[20];
    int top = 0;
 
    if (!x) {
        putchar('0');
        return;
    }
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    while (x) {
        buf[++top] = (x % 10) | 48;
        x /= 10;
    }
    while (top)
        putchar(buf[top--]);
}
inline void write(int x) { writeint(x); }
inline void write(unsigned x) { writeint(x); }
inline void write(int64 x) { writeint(x); }
inline void write(uint64 x) { writeint(x); }
inline void write(char ch) { putchar(ch); }
inline void write(char *s) {
	while(*s) {
		putchar(*s);
		s++;
	}
}
inline void write(const char *s) { printf(s); }
T1 inline void write_(A x) {
    write(x);
    putchar(' ');
}
T1 inline void writeln(A x) {
    write(x);
    putchar('\n');
}
T2 inline void write(A a, B b) {
    write_(a);
    write(b);
}
T2 inline void writeln(A a, B b) {
    write_(a);
    writeln(b);
}
T3 inline void writeln(A a, B b, C c) {
    write_(a);
    write_(b);
    writeln(c);
}
T4 inline void writeln(A a, B b, C c, D d) {
    write_(a);
    write_(b);
    write_(c);
    writeln(d);
}
#undef T1
#undef T2
#undef T3
#undef T4


const int N = 1000 + 10;

int n, m;
int p[15], pn;

bool query(int h, int w, int i1, int j1, int i2, int j2) {
	putchar('?');
	putchar(' ');
	write_(h);
	write_(w);
	write_(i1);
	write_(j1);
	write_(i2);
	writeln(j2);
	fflush(stdout);
	int x;
	read(x);
	return x;
}
bool query1(int h, int i2) { return query(h, m, 1, 1, i2, 1); }
bool query2(int w, int j2) { return query(n, w, 1, 1, 1, j2); }

int d(int n) {
	int i, res = 0;
	
	for(i=1; i<=n; i++)
		if(n % i == 0)
			res++;
	return res;
}

int main() {
	int n0, m0;
	int i, x, k;
	
	read(n, m);
	n0 = n;
	m0 = m;
	
	x = n;
	for(i=2; i*i<=x; i++) {
		while(!(x % i)) {
			p[++pn] = i;
			x /= i;
		}
	}
	if(x > 1)
		p[++pn] = x;
	Fo(i, pn) {
		k = n / p[i];
		if(p[i] == 2 and query1(k, 1 + k))
			n /= 2;
		else if(p[i] > 2 and query1(p[i] / 2 * k, 1 + p[i] / 2 * k) and query1(p[i] / 2 * k, 1 + p[i] / 2 * k + k))
			n /= p[i];
	}
	
	pn = 0;
	x = m;
	for(i=2; i*i<=x; i++) {
		while(!(x % i)) {
			p[++pn] = i;
			x /= i;
		}
	}
	if(x > 1)
		p[++pn] = x;
	Fo(i, pn) {
		k = m / p[i];
		if(p[i] == 2 and query2(k, 1 + k))
			m /= 2;
		else if(p[i] > 2 and query2(p[i] / 2 * k, 1 + p[i] / 2 * k) and query2(p[i] / 2 * k, 1 + p[i] / 2 * k + k))
			m /= p[i];
	}
	
	putchar('!');
	putchar(' ');
	writeln(d(n0 / n) * d(m0 / m));
	fflush(stdout);
	return 0;
}