#include <bits/stdc++.h>
using namespace std;
typedef long long Long;

//const Long MX = ;
const Long K=10000011;

Long fact[K];

void extSieve(){
	for( Long i=2; i*i < K; ++i ){
		if( fact[ i ] == 0 ){
			for( Long j = i*i ; j < K ; j+=i ) if( fact[j ] == 0) fact[ j ] = i;
		}
	}
	for( Long i=2; i<K; ++i ){
		if( fact[ i ] == 0 ){
			fact[ i ] = i;
		}
	}
}

bool query(vector<Long> &v){
	cout << "?";
	for(Long i = 0; i < 6; i++) cout << " " << v[i];
	cout << endl;
	Long ans;
	cin >> ans;
	return ans;
}

bool can(Long cnt, Long n, Long m, Long t){
	if(cnt % 2 == 0){
		vector<Long> q = {n/cnt,m,1,1,n/cnt+1,1};
		if(t == 1) swap(q[0],q[1]), swap(q[2],q[3]), swap(q[4],q[5]);
		return query(q);
	}
	Long aux = cnt / 2;
	vector<Long> q1 = {(n/cnt)*aux,m,1,1,(n/cnt)*aux+1,1};
	vector<Long> q2 = {(n/cnt)*aux,m,(n/cnt)+1,1,(n/cnt)*(aux+1)+1,1};
	if(t == 1) swap(q1[0],q1[1]), swap(q1[2],q1[3]), swap(q1[4],q1[5]);
	if(t == 1) swap(q2[0],q2[1]), swap(q2[2],q2[3]), swap(q2[4],q2[5]);
	return (query(q1) & query(q2));
}

Long cal(Long n, Long m, Long t){
	Long ans = 1;
	Long nn = n;
	
	Long auxi = 0;
	while(nn % 2 == 0){
		nn /= 2;
		auxi++;
	}
	Long last = 1;
	Long auxii = 1;
	Long curr = 0;
	for(Long i = 0; i < auxi; i++){
		auxii *= 2;
		last = (last & can(auxii,n,m,t));
		curr += last;
	}
	ans *= (curr + 1);
	
	while(nn > 1){
		Long f = fact[nn];
		Long exp = 0;
		while(nn % f == 0){
			nn /= f;
			exp++;
		}
		Long bloq = 1;
		curr = 0;
		for(Long i = 0; i < exp; i++){
			bloq *= f;
			curr += can(bloq,n,m,t);
		}
		ans *= (curr + 1);
	}
	return ans;
}

int main(){
	extSieve();
	
	Long n, m;
	cin >> n >> m;
	
	Long cntn = cal(n,m,0);
	Long cntm = cal(m,n,1);
	
	cout << "! " << cntn * cntm << "\n";
	return 0;
}
