using System; using System.IO; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using E = System.Linq.Enumerable; using MatrixType = System.Int64; using System.Numerics; partial class Solver { static public Tuple Gcd(Tuple s, Tuple t) { //return t != 0 ? Gcd(t, s % t) : s; if (t.Item1 == 0 && t.Item2 == 0) return s; var a = long.MaxValue; if (t.Item1 > 0) a = Math.Min(a, s.Item1 / t.Item1); if (t.Item2 > 0) a = Math.Min(a, s.Item2 / t.Item2); return Gcd(t, Tuple.Create(s.Item1 - a * t.Item1, s.Item2 - a * t.Item2)); } public void Run() { var a = nl(); var b = nl(); var c = nl(); var d = nl(); var N = ni(); var x = new int[N]; var y = new int[N]; for (int i = 0; i < N; i++) { x[i] = ni(); y[i] = ni(); } var det = Math.Abs(a * d - b * c); var set = new HashSet>(); if (det == 0) { var g = Gcd(Tuple.Create(a, b), Tuple.Create(c, d)); for (int i = 0; i < N; i++) { var xx = (long)x[i]; var yy = (long)y[i]; var t = long.MaxValue; if (g.Item1 > 0) t = Math.Min(t, xx / g.Item1); if (g.Item2 > 0) t = Math.Min(t, yy / g.Item2); xx -= t * g.Item1; yy -= t * g.Item2; set.Add(Tuple.Create(xx, yy)); } } else { var M = new Matrix(new long[,] { { d, -c }, { -b, a }, }); for (int i = 0; i < N; i++) { var mat = new Matrix(new long[,] { { x[i] }, { y[i] }, }); var r = M * mat; var xx = r[0, 0] % det; if (xx < 0) xx += det; var yy = r[0, 1] % det; if (yy < 0) yy += det; set.Add(Tuple.Create(xx, yy)); } } cout.WriteLine(set.Count); } } //using MatrixType = ModInt; public class Matrix { public int Row { get; private set; } public int Col { get; private set; } private MatrixType[] Data; public Matrix(int row, int col) { this.Row = row; this.Col = col; this.Data = new MatrixType[Row * Col]; } public Matrix(MatrixType[,] array) : this(array.GetLength(0), array.GetLength(1)) { int index = 0; for (int i = 0; i < Row; i++) { for (int j = 0; j < Col; j++) { Data[index++] = array[i, j]; } } } public MatrixType this[int row, int col] { set { Data[row * Col + col] = value; } get { return Data[row * Col + col]; } } static public Matrix UnitMatrix(int n) { var matrix = new Matrix(n, n); for (int i = 0; i < n; i++) { matrix[i, i] = 1; } return matrix; } static public Matrix operator +(Matrix A, Matrix B) { var C = new Matrix(A.Row, A.Col); for (int i = 0; i < C.Data.Length; i++) { C.Data[i] = A.Data[i] + B.Data[i]; } return C; } static public Matrix operator -(Matrix A, Matrix B) { var C = new Matrix(A.Row, A.Col); for (int i = 0; i < C.Data.Length; i++) { C.Data[i] = A.Data[i] - B.Data[i]; } return C; } static public Matrix operator *(Matrix A, Matrix B) { var C = new Matrix(A.Row, B.Col); for (int i = 0; i < A.Row; i++) { for (int j = 0; j < B.Col; j++) { var val = C[i, j]; for (int k = 0; k < A.Col; k++) val += A[i, k] * B[k, j]; C[i, j] = val; } } return C; } public static implicit operator Matrix(MatrixType[,] array) { return new Matrix(array); } static public Matrix Pow(Matrix A, long n) { if (n == 0) return UnitMatrix(A.Row); Matrix result = A.Clone(), t = A.Clone(); n--; while (n > 0) { if ((n & 1) != 0) { result = result * t; } t = t * t; n >>= 1; } return result; } public Matrix Clone() { return new Matrix(Row, Col) { Data = Data.Clone() as MatrixType[] }; } static private void Swap(ref T a, ref T b) { T t = a; a = b; b = t; } static public double Determinant(Matrix matrix) { if (matrix.Row != matrix.Col) throw new ArgumentException(); var n = matrix.Col; const double Error = 1e-12; var m = new double[n][]; for (int i = 0; i < n; i++) { var r = new double[n]; for (int j = 0; j < n; j++) r[j] = matrix[i, j]; m[i] = r; } double d = 1; for (int i = 0; i < n; i++) { var targetRow = -1; var pivot = Error; for (int r = i; r < n; r++) { var row = m[r]; if (Math.Abs(row[i]) > Math.Abs(pivot)) { targetRow = r; pivot = row[i]; } } if (targetRow == -1) return 0; if (i != targetRow) { Swap(ref m[i], ref m[targetRow]); d *= -1; } d *= pivot; var mi = m[i]; for (int r = i + 1; r < n; r++) { var row = m[r]; var weight = row[i] / pivot; for (int k = i + 1; k < n; k++) row[k] -= weight * mi[k]; } } return d; } } // PREWRITEN CODE BEGINS FROM HERE partial class Solver : Scanner { public static void Main(string[] args) { #if LOCAL new Solver(Console.In, Console.Out).Run(); #else Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false }); new Solver(Console.In, Console.Out).Run(); Console.Out.Flush(); #endif } #pragma warning disable IDE0052 private readonly TextReader cin; private readonly TextWriter cout; #pragma warning restore IDE0052 public Solver(TextReader reader, TextWriter writer) : base(reader) { this.cin = reader; this.cout = writer; } public Solver(string input, TextWriter writer) : this(new StringReader(input), writer) { } #pragma warning disable IDE1006 #pragma warning disable IDE0051 private int ni() { return NextInt(); } private int[] ni(int n) { return NextIntArray(n); } private long nl() { return NextLong(); } private long[] nl(int n) { return NextLongArray(n); } private double nd() { return NextDouble(); } private double[] nd(int n) { return NextDoubleArray(n); } private string ns() { return Next(); } private string[] ns(int n) { return NextArray(n); } #pragma warning restore IDE1006 #pragma warning restore IDE0051 } public static class LinqPadExtension { static public T Dump(this T obj) { #if LOCAL return LINQPad.Extensions.Dump(obj); #else return obj; #endif } } public class Scanner { private readonly TextReader Reader; private readonly Queue TokenQueue = new Queue(); private readonly CultureInfo ci = CultureInfo.InvariantCulture; public Scanner() : this(Console.In) { } public Scanner(TextReader reader) { this.Reader = reader; } public int NextInt() { return int.Parse(Next(), ci); } public long NextLong() { return long.Parse(Next(), ci); } public double NextDouble() { return double.Parse(Next(), ci); } public string[] NextArray(int size) { var array = new string[size]; for (int i = 0; i < size; i++) array[i] = Next(); return array; } public int[] NextIntArray(int size) { var array = new int[size]; for (int i = 0; i < size; i++) array[i] = NextInt(); return array; } public long[] NextLongArray(int size) { var array = new long[size]; for (int i = 0; i < size; i++) array[i] = NextLong(); return array; } public double[] NextDoubleArray(int size) { var array = new double[size]; for (int i = 0; i < size; i++) array[i] = NextDouble(); return array; } public string Next() { if (TokenQueue.Count == 0) { if (!StockTokens()) throw new InvalidOperationException(); } return TokenQueue.Dequeue(); } public bool HasNext() { if (TokenQueue.Count > 0) return true; return StockTokens(); } static readonly char[] _separator = new[] { ' ' }; private bool StockTokens() { while (true) { var line = Reader.ReadLine(); if (line == null) return false; var tokens = line.Split(_separator, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length == 0) continue; foreach (var token in tokens) TokenQueue.Enqueue(token); return true; } } }