Two pictures
Difficulty: Hard

You have been assigned to an important job. The software company you are working with requires you to develop a module for his new social network. This task is simple as they will provide you a big and a smaller picture as a pattern. They are looking for the part within the big one which is more likely to be the pattern.

The more likely part is the one which minimizes the sum of the squared differences over all H * W.Each pixel in the big picture and the pattern picture is an integer with absolute value at most 30.

**Input specification**

The input starts with the description of the big picture. It is described from the top to bottom and from left to right. The dimension of the big one, R and C (1 <= R, C <= 500) are given in the first line, followed by R lines of C integer, describing each pixel of the big picture. Following is the description of a pattern picture, starting with dimensions  H and W (1 <= H, W <= 499), and then H lines of W integers.

**Output specification**

Output is exactly one line, in the form of 'R C V', where V is the least sum of squared differences over all H * W, the one which starts at row R and col C. If there are several solutions, prints the closest to the top of the big picture. If there is still several solutions, chooses the closest to the left.(quotes for clarity only).

**Sample input**
<br>3 3
<br>1 2 3
<br>4 5 6
<br>7 8 9
<br>2 2
<br>2 1
<br>3 4

**Sample output**
<br>1 1 4

Input Format:

Output Format:

Sample Input:

Sample Output:

Python 3 starter code:


Reference solution (C++):
<pre>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#include <stack>
#include <cassert>
#include <algorithm>
using namespace std;

typedef unsigned long long ll;

#define XX double

struct P {
	XX x, y;
	P() {

	}
	P(XX x, XX y) :
		x(x), y(y) {
	}
	inline P operator-(const P b) {
		return P(x - b.x, y - b.y);
	}
	inline P operator+(const P b) {
		return P(x + b.x, y + b.y);
	}
	inline P operator*(const P b) {
		return P(x * b.x - y * b.y, x * b.y + y * b.x);
	}
	inline P operator/(const P b) {
		P s = P(x * b.x + y * b.y, y * b.x - x * b.y);
		s.x /= (b.x * b.x + b.y * b.y);
		s.y /= (b.x * b.x + b.y * b.y);
		return s;
	}
};
// (a,b) * (c,d) = (ac-bd, ad+bc)
// (a,b) / (c,d) = ( (ac+bd) / (c^2+d^2), (bc-ad) / (c^2+d^2) )


const double PI = 3.141592653589793;

void fft(P *a, int n, bool invert) {
	for (register int i = 1, j = 0; i < n; ++i) {
		int bit = n >> 1;
		for (; j >= bit; bit >>= 1)
			j -= bit;
		j += bit;
		if (i < j)
			swap(a[i], a[j]);
	}
	for (register int len = 2; len <= n; len <<= 1) {
		double ang = 2 * PI / len * (invert ? -1 : 1);
		P wlen(cos(ang), sin(ang));
		for (int i = 0; i < n; i += len) {
			P w(1, 0);
			for (int j = 0; j < len / 2; ++j) {
				P u = a[i + j], v = a[i + j + len / 2] * w;
				a[i + j] = u + v;
				a[i + j + len / 2] = u - v;
				w = w * wlen;
			}
		}
	}
	if (invert)
		for (int i = 0; i < n; ++i)
			a[i].x /= n, a[i].y /= n;
}

int R, C, H, W, k, ii, jj;
int F[700][700];
int Pa[700][700];
int SumSumF[700][700];

P A[2200000], B[2200000];

int ptr;

ll SumSumP , score;

inline int correct(double val) {
	if(val < 0) return val - 0.5;
	return val + 0.5;
}

int rs, cs;
ll sol;

int main() {

	sol = 2 * 1e18;

	scanf("%d%d", &R, &C);
	for(int i = 0;i<R;i++)
		for(int j = 0;j<C;j++) {
			scanf("%d", &F[i][j]);
			A[i * C + j].x = F[i][j];
			SumSumF[i+1][j+1] = F[i][j] * F[i][j];
			SumSumF[i+1][j+1] += SumSumF[i][j+1] + SumSumF[i+1][j] - SumSumF[i][j];
		}

	scanf("%d%d", &H, &W);

	for(int i = 0;i<H;i++)
		for(int j = 0;j<W;j++) {
			scanf("%d", &Pa[i][j]);
			B[i * C + j].x = Pa[i][j];
			SumSumP += Pa[i][j] * Pa[i][j];
		}

	int nn = 1;
	while((1<<nn) <= R * C) ++nn;
	nn = 1<<nn;

	fft(A, nn, false);
	fft(B, nn, false);

	for(int i = 0;i<nn;i++)
		A[i] = A[i] * B[-i & (nn-1)];

	fft(A, nn, true);

	for(int i = 0;i<R-H+1;i++)
		for(int j = 0;j<C-W+1;j++) {
			score = SumSumP;
			score += SumSumF[i+H][j+W] - SumSumF[i][j+W] - SumSumF[i+H][j] + SumSumF[i][j];
			score -= 2 *  correct(A[ i * C + j ].x);
			if(score < sol) {
				sol = score;
				rs = i + 1;
				cs = j + 1;
			}
		}

	printf("%d %d %lld\n", rs, cs, sol);
	return 0;
}