Problem:
Reflection

For given three points p1, p2, p, find the reflection point x of p onto p1p2.

Input

xp1 yp1 xp2 yp2
q
xp0 yp0
xp1 yp1
...
xpq−1 ypq−1

In the first line, integer coordinates of p1 and p2 are given. Then, q queries are given for integer coordinates of p.

Output

For each query, print the coordinate of the reflection point x. The output values should be in a decimal fraction with an error less than 0.00000001.

Constraints

1 ≤ q ≤ 1000

-10000 ≤ xi, yi ≤ 10000

p1 and p2 are not identical.

Sample Input 1

0 0 2 0
3
-1 1
0 1
1 1

Sample Output 1

-1.0000000000 -1.0000000000
0.0000000000 -1.0000000000
1.0000000000 -1.0000000000

Sample Input 2

0 0 3 4
3
2 5
1 4
0 3

Sample Output 2

4.2400000000 3.3200000000
3.5600000000 2.0800000000
2.8800000000 0.8400000000

Solution in JAVA (judge verdict: Accepted)

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;

public class Main {
	static boolean debug = false;

	public static void main(String[] args) throws IOException {

		UserScanner scan = new UserScanner();
		PrintWriter pwriter = new PrintWriter(System.out);

		int x0 = scan.nextInt();
		int y0 = scan.nextInt();
		int x1 = scan.nextInt();
		int y1 = scan.nextInt();

		Projection projection = new Projection(x0, y0, x1, y1);

		int q = scan.nextInt();
		for (int i = 0; i < q; i++) {
			int x2 = scan.nextInt();
			int y2 = scan.nextInt();
			projection.calc(x2, y2, pwriter);
		}
		pwriter.flush();

		scan.close();
		System.exit(0);
	}
}

class Projection {
	// rotate right and adjust line (x0,y0)-(x1,y1) to horizontal
	// ' (dash) means rotated
	// x2' = x2*cos+y2*sin
	// y2' = -x2*sin+y2*cos
	// x0' = x0*cos+y0*sin
	// y0' = -x0*sin+y0*cos

	// reflection point (x2'',y2'') is (x2',y0'-(y2'-y0')) equal to
	// (x2',2*y0'-y2')

	// rotate left and gain axis, required point (tx,ty) is
	// tx = x2''*cos-y2''*sin
	// = x2'*cos-(2*y0'-y2')*sin
	// = (x2*cos+y2*sin)*cos-(-2*x0*sin+2*y0*cos+x2*sin-y2*cos)*sin
	// = x2*cos*cos+y2*sin*cos+2*x0*sin*sin-2*y0*sin*cos-x2*sin*sin+y2*sin*cos
	// = x2*(cos*cos-sin*sin)+2*y2*sin*cos +2*x0*sin*sin-2*y0*sin*cos
	//
	// ty = x2''*sin+y2''*cos
	// = x2'*sin+(2*y0'-y2')*cos
	// = (x2*cos+y2*sin)*sin+(-2*x0*sin+2*y0*cos+x2*sin-y2*cos)*cos
	// = x2*sin*cos+y2*sin*sin-2*x0*sin*cos+2*y0*cos*cos+x2*sin*cos-y2*cos*cos
	// = 2*x2*sin*cos+y2*(sin*sin-cos*cos) -2*x0*sin*cos+2*y0*cos*cos

	double cos2, sin2, sincos, cos2msin2;
	double txd, tyd;

	public Projection(int x0, int y0, int x1, int y1) {
		double t2 = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
		cos2 = (x1 - x0) * (x1 - x0) / t2;
		sin2 = (y1 - y0) * (y1 - y0) / t2;
		sincos = (x1 - x0) * (y1 - y0) / t2;
		txd = 2 * x0 * sin2 - 2 * y0 * sincos;
		tyd = -2 * x0 * sincos + 2 * y0 * cos2;
	}

	public void calc(int x2, int y2, PrintWriter pw) {
		double tx = x2 * (cos2 - sin2) + 2 * y2 * sincos + txd;
		double ty = 2 * x2 * sincos + y2 * (sin2 - cos2) + tyd;
		pw.print(String.valueOf(tx));
		pw.print(' ');
		pw.println(String.valueOf(ty));
	}
}

class UserScanner {
	private final InputStream in = System.in;
	private final byte[] buffer = new byte[1024];
	private int ptr = 0;
	private int buflen = 0;

	private boolean read() throws IOException {
		ptr = 0;
		buflen = in.read(buffer);
		if (buflen <= 0)
			return false;
		else
			return true;
	}

	private byte getByte() throws IOException {
		if (ptr >= buflen)
			read();
		if (isCtlSpace(buffer[ptr])) {
			return -1;
		} else
			return buffer[ptr++];
	}

	private void skipCtlSpace() throws IOException {
		if (ptr >= buflen)
			read();
		if (isCtlSpace(buffer[ptr])) {
			ptr++;
			skipCtlSpace();
		}
	}

	private boolean isCtlSpace(byte b) {
		if (b <= ' ' || b > '~')
			return true;
		else
			return false;
	}

	public void close() throws IOException {
		in.close();
	}

	public String next() throws IOException {
		skipCtlSpace();
		StringBuilder sb = new StringBuilder();
		byte b;
		while ((b = getByte()) != -1) {
			sb.appendCodePoint(b);
		}
		return sb.toString();
	}

	public int nextInt() throws IOException {
		skipCtlSpace();
		int n = 0;
		boolean minus = false;
		byte b;
		while ((b = getByte()) != -1) {
			if (b == '-')
				minus = true;
			else {
				n *= 10;
				n += (b - '0');
			}
		}
		if (minus)
			return n * -1;
		else
			return n;
	}
}