[THE SxPLAY & KIVΛ - 漂流](https://soundcloud.com/kivawu/hyouryu)

[KIVΛ & Nikki Simmons - Perspectives](https://soundcloud.com/kivawu/perspectives)

With a new body, our idol Aroma White (or should we call her Kaori Minamiya?) begins to uncover her lost past through the OS space.

The space can be considered a 2D plane, with an infinite number of data nodes, indexed from 0, with their coordinates defined as follows:

  * The coordinates of the 0-th node is (x_0, y_0) 
  * For i > 0, the coordinates of i-th node is (a_x ⋅ x_{i-1} + b_x, a_y ⋅ y_{i-1} + b_y) 



Initially Aroma stands at the point (x_s, y_s). She can stay in OS space for at most t seconds, because after this time she has to warp back to the real world. She doesn't need to return to the entry point (x_s, y_s) to warp home.

While within the OS space, Aroma can do the following actions:

  * From the point (x, y), Aroma can move to one of the following points: (x-1, y), (x+1, y), (x, y-1) or (x, y+1). This action requires 1 second. 
  * If there is a data node at where Aroma is staying, she can collect it. We can assume this action costs 0 seconds. Of course, each data node can be collected at most once. 



Aroma wants to collect as many data as possible before warping back. Can you help her in calculating the maximum number of data nodes she could collect within t seconds?

Input

The first line contains integers x_0, y_0, a_x, a_y, b_x, b_y (1 ≤ x_0, y_0 ≤ 10^{16}, 2 ≤ a_x, a_y ≤ 100, 0 ≤ b_x, b_y ≤ 10^{16}), which define the coordinates of the data nodes.

The second line contains integers x_s, y_s, t (1 ≤ x_s, y_s, t ≤ 10^{16}) – the initial Aroma's coordinates and the amount of time available.

Output

Print a single integer — the maximum number of data nodes Aroma can collect within t seconds.

Examples

Input


1 1 2 3 1 0
2 4 20


Output


3

Input


1 1 2 3 1 0
15 27 26


Output


2

Input


1 1 2 3 1 0
2 2 1


Output


0

Note

In all three examples, the coordinates of the first 5 data nodes are (1, 1), (3, 3), (7, 9), (15, 27) and (31, 81) (remember that nodes are numbered from 0).

In the first example, the optimal route to collect 3 nodes is as follows: 

  * Go to the coordinates (3, 3) and collect the 1-st node. This takes |3 - 2| + |3 - 4| = 2 seconds. 
  * Go to the coordinates (1, 1) and collect the 0-th node. This takes |1 - 3| + |1 - 3| = 4 seconds. 
  * Go to the coordinates (7, 9) and collect the 2-nd node. This takes |7 - 1| + |9 - 1| = 14 seconds. 



In the second example, the optimal route to collect 2 nodes is as follows: 

  * Collect the 3-rd node. This requires no seconds. 
  * Go to the coordinates (7, 9) and collect the 2-th node. This takes |15 - 7| + |27 - 9| = 26 seconds. 



In the third example, Aroma can't collect any nodes. She should have taken proper rest instead of rushing into the OS space like that.
	import java.io.*;
	import java.math.*;
	import java.util.*;
	
	/**
	 *
	 * @author Saju
	 *
	 */
	
	public class Main {
	
		private static int dx[] = { 1, 0, -1, 0};
		private static int dy[] = { 0, -1, 0, 1};
	
		private static final long INF = Long.MAX_VALUE;
		private static final int INT_INF = Integer.MAX_VALUE;
		private static final long NEG_INF = Long.MIN_VALUE;
		private static final int NEG_INT_INF = Integer.MIN_VALUE;
		private static final double EPSILON = 1e-10;
	
		private static final int MAX = 1007;
		private static final long MOD = 1000000007;
		
		private static final int MAXN = 100007;
		private static final int MAXA = 10000009;
		private static final int MAXLOG = 22;
	
		public static void main(String[] args) {
	
			InputReader in = new InputReader(System.in);
			PrintWriter out = new PrintWriter(System.out);
			
	
	/*
	
	
	
	*/
			
		
			long x0 = in.nextLong();
			long y0 = in.nextLong();
			long ax = in.nextLong();
			long ay = in.nextLong();
			long bx = in.nextLong();
			long by = in.nextLong();
			
			long xs = in.nextLong();
			long ys = in.nextLong();
			long t = in.nextLong();
			
			List<Point> list = new ArrayList<Main.Point>();
			long x = x0;
			long y = y0;
			
			list.add(new Point(x, y));
			long LIMIT = ((long)1 << 62);
			while((LIMIT - bx) / ax >= x && (LIMIT - by) / ay >= y) {
				long x1 = (ax * x) + bx;
				long y1 = (ay * y) + by;
				if(x1 < x || y1 < y) {
					break;
				}
				x = x1; 
				y = y1;
				list.add(new Point(x, y));
			}
			int sz = list.size();
//			System.out.println(t);
//			for(Point p : list) {
//				System.out.println(p);
//			}
			long max = 0;
			for(int i = 0; i < sz; i++) {
				Point p = list.get(i);
				long x1 = p.x;
				long y1 = p.y;
				long sum = abs(xs - x1) + abs(ys - y1);
				
				int count = 0;
				int j = i;
				while(sum <= t) {
					count++;
					if(j + 1 < sz) {
						Point p1 = list.get(j);
						Point p2 = list.get(j + 1);
						sum = sum + abs(p2.x - p1.x) + abs(p2.y - p1.y);
					}
					else {
						break;
					}
					j++;
				}
				max = max(max, count);
			}
			
			for(int i = 0; i < sz; i++) {
				Point p = list.get(i);
				long x1 = p.x;
				long y1 = p.y;
				long sum = abs(xs - x1) + abs(ys - y1);
				
				int count = 0;
				int j = i;
				while(sum <= t) {
					count++;
					if(j > 0) {
						Point p1 = list.get(j);
						Point p2 = list.get(j - 1);
						sum = sum + abs(p2.x - p1.x) + abs(p2.y - p1.y);
					}
					else {
						break;
					}
					j--;
				}
				max = max(max, count);
			}
//			if(x0 >= (INF / ax) || y0 >= (INF / ay)) {
//				max = 1;
//			}
			System.out.println(max);
			
			
			out.flush();
			out.close();
			System.exit(0);
		}
		
		
		private static class Graph{
			private int node;
			private List<Edge>[] adj;
			
			Graph(int node){
				this.node = node;
				adj = new ArrayList[this.node];
				for(int i = 0; i < node; i++) {
					adj[i] = new ArrayList<Main.Edge>();
				}
			}
			
			void addEdge(int u, int v, long cost) {
				Edge e = new Edge(u, v, cost);
				Edge e1 = new Edge(v, u, cost);
				adj[u].add(e);
				adj[v].add(e1);
			}
			
			long[] calculateShortestPath(int source) {
				
				long dist[] = new long[node];
				PriorityQueue<Node> queue = new PriorityQueue<Main.Node>(new Comparator<Node>() {
	
					@Override
					public int compare(Node o1, Node o2) {
						int val = Long.compare(o1.distance, o2.distance);
						return val;
						
					}
				});
				
				Arrays.fill(dist, INT_INF);
				
				queue.add(new Node(source, 0));
				dist[source] = 0;
				
				while(!queue.isEmpty()) {
					Node nn = queue.remove();
					int u = nn.node;
					long udist = nn.distance;
					if(udist > dist[u]) {
						continue;
					}
					for(Edge e : adj[u]) {
							int v = e.v;
							long vdist = e.cost;
							long arrive = udist + vdist;
							if(arrive < dist[v]) {
								dist[v] = arrive;
								queue.add(new Node(v, dist[v]));
	//							System.out.println(u + " " + v + " " + vdist + " " + dist[v]);
							}
						
					}
					
				}
				return dist;
				
			}
		}
		
		private static class Node{
			int operation;
			int node;
			long distance;
			Node(int operation, int node, long distance){
				this.operation = operation;
				this.node = node;
				this.distance = distance;
			}
			
			Node(int node, long distance){
				this.node = node;
				this.distance = distance;
			}
		}
		
		private static class Edge{
			int u;
			int v;
			long cost;
			
			Edge(int u, int v, long cost){
				this.u = u;
				this.v = v;
				this.cost = cost;
			}
			
			int getNeighbourIndex(int node) {
				if(this.u == node) {
					return v;
				}
				return u;
			}
		}
		
		private static boolean isPalindrome(String str) {
			StringBuilder sb = new StringBuilder();
			sb.append(str);
			String str1 = sb.reverse().toString();
			return str.equals(str1);
	 	}
	
		private static String reverseString(String str) {
			StringBuilder sb = new StringBuilder();
			sb.append(str);
			return sb.reverse().toString();
		}
		
		
		private static double distance(Point p1, Point p2) {
			long divx = p2.x - p1.x;
			long divy = p2.y - p1.y;
			divx = divx * divx;
			divy = divy * divy;
			return Math.sqrt(divx + divy);
		}
		
		private static String getBinaryStr(int n, int j) {
			String str = Integer.toBinaryString(n);
			int k = str.length();
			for(int i = 1; i <= j - k; i++) {
				str = "0" + str;
			}
			
			return str;
		}
	
		// O(log(max(A,M)))
		static long modInverse(long a, long m) {
			extendedEuclid(a, m);
			return (x % m + m) % m;
		}
	
		static long x;
		static long y;
		static long gcdx;
	
		private static void extendedEuclid(long a, long b) {
			if (b == 0) {
				gcdx = a;
				x = 1;
				y = 0;
			} else {
				extendedEuclid(b, a % b);
				long temp = x;
				x = y;
				y = temp - ((a / b) * y);
			}
		}
		
		private static void generatePrime(int n) {
			 //O(NloglogN)
			boolean arr[] = new boolean[n + 5];
			Arrays.fill(arr, true);
			for(int i = 2; i * i <=n; i++){
				if(arr[i] == true){
					for(int j = i * i; j <= n; j+=i){
						arr[j] = false; 
					}
				}
			}
			int count = 0;
			int start = 0;
			for(int i = 2; i <= n; i++){
				if(arr[i] == true){
	//				System.out.println(i + " ");
					count++;
				}
				if(count == (start * 100) + 1) {
	//				System.out.println(i);
					start++;
				}
			}
			System.out.println();
			System.out.println(count);
			
		}
		
		private static Map<Long, Long> primeFactorization(long n, long m){
			Map<Long, Long> map = new HashMap<>();
			
			for(long i = 2; i <= Math.sqrt(n); i++){
				if(n % i == 0){
				long count = 0;
				while(n % i == 0){
					count++;
					n = n / i;
				}
				long val = count * m;
				map.put(i, val);
	//			System.out.println("i: " + i + ", count: " + count);
			}
				
			}
			if(n != 1) {
	//			System.out.println(n);
				map.put(n, m);
			}
			return map;
		}
	
		private static class Pair<T>{
			T a;
			T b;
			Pair(T a, T b){
				this.a = a;
				this.b = b;
			}
		}
		
		private static class SegmentTree{
			int n;
			private final int MAXN = 100007;
			private long[] tree = new long[MAXN << 2];
			private long[] lazy = new long[MAXN << 2];
			private long[] arr = new long[MAXN];
			
			
			/***
			 * 
			 * arr is 1 based index.
			 * 
			 * @param arr
			 * 
			 */
			SegmentTree(int n, long[] arr){
				this.n = n;
				for(int i = 0; i < arr.length; i++) {
					this.arr[i] = arr[i];
				}
			}
			
			void build(int index, int left, int right) {
				if(left == right) {
					tree[index] = arr[left];
				}
				else {
					int mid = (left + right) / 2;
					
					build(index * 2, left, mid);
					build((index * 2) + 1, mid + 1, right);
					tree[index] = max(tree[(index * 2)], tree[(index * 2) + 1]);
				}
			}
			
			long query(int node, int left, int right, int start, int end) {
				
				if(left > end || right < start) {
					return NEG_INF;
				}
				
				if(left >= start && right <= end) {
					return tree[node];
				}
				int mid = (left + right) / 2;
				long val1 = query(2 * node, left, mid, start, end);
				long val2 = query(2 * node + 1, mid + 1, right, start, end);
				
				return max(val1, val2);
			}
			
			void update(int node, int left, int right, int idx, long val) {
				if(left == right) {
					tree[node] += val;
				}
				else {
					int mid = (left + right) / 2;
					if(idx <= mid) {
						update(2 * node, left, mid, idx, val);
					}
					else {
						update(2 * node + 1, mid + 1, right, idx, val);
					}
					tree[node] = max(tree[(2 * node) + 1], tree[(2 * node)]);
				}
			}
			
			
	
			 void updateRange(int node, int start, int end, int l, int r, long val)
			{
			    if(lazy[node] != 0)
			    { 
			        // This node needs to be updated
			        tree[node] =  lazy[node];    // Update it
			        if(start != end)
			        {
			            lazy[node*2] = lazy[node];                  // Mark child as lazy
			            lazy[node*2+1] = lazy[node];                // Mark child as lazy
			        }
			        lazy[node] = 0;                                  // Reset it
			    }
			    if(start > end || start > r || end < l)              // Current segment is not within range [l, r]
			        return;
			    if(start >= l && end <= r)
			    {
			        // Segment is fully within range
			        tree[node] =  val;
			        if(start != end)
			        {
			            // Not leaf node
			            lazy[node*2] = val;
			            lazy[node*2+1] = val;
			        }
			        return;
			    }
			    int mid = (start + end) / 2;
			    updateRange(node*2, start, mid, l, r, val);        // Updating left child
			    updateRange(node*2 + 1, mid + 1, end, l, r, val);   // Updating right child
			    tree[node] = max(tree[node*2], tree[node*2+1]);        // Updating root with max value 
			}
	
			 long queryRange(int node, int start, int end, int l, int r)
			{
			    if(start > end || start > r || end < l)
			        return 0;         // Out of range
			    if(lazy[node] != 0)
			    {
			        // This node needs to be updated
			        tree[node] =  lazy[node];            // Update it
			        if(start != end)
			        {
			            lazy[node*2] = lazy[node];         // Mark child as lazy
			            lazy[node*2+1] = lazy[node];    // Mark child as lazy
			        }
			        lazy[node] = 0;                 // Reset it
			    }
			    if(start >= l && end <= r)             // Current segment is totally within range [l, r]
			        return tree[node];
			    int mid = (start + end) / 2;
			    long p1 = queryRange(node*2, start, mid, l, r);         // Query left child
			    long p2 = queryRange(node*2 + 1, mid + 1, end, l, r); // Query right child
			    return max(p1, p2);
			}
			
			 void buildRange(int node, int low, int high){
				if(low == high){
					tree[node] =  arr[low];
					return;
				}
				
				int mid = (low + high) / 2;
				int left = node << 1;
				int right = left | 1;
				buildRange(left, low, mid);
				buildRange(right, mid + 1, high);
				tree[node] = max(tree[left], tree[right]);
			}
			
			
			void printSegmentTree() {
				System.out.println(Arrays.toString(tree));
			}
			
		}
		
		private static class KMP{
			
			private static char[] t;
			private static char[] s;
			
			public int kmp(char[]t, char[]s) {
				this.t = t;
				this.s = s;
				return this.kmp();
			}
			
			private int kmp() {
				
				List<Integer> prefixTable = getPrefixTable(s);
				
				int match = 0;
				int i = 0;
				int j = 0;
				
				int n = t.length;
				int m = s.length;
				while(i < n) {
					if(t[i] == s[j]) {
						if(j == m - 1) {
							match++;
							j = prefixTable.get(j - 1);
							continue;
						}
						i++;
						j++;
					}
					else if(j > 0) {
						j = prefixTable.get(j - 1);
					}
					else {
						i++;
					}
				}
				
				return match;
			}
	
			/***
			1. We compute the prefix values π[i] in a loop by iterating 	<br/>
					from i=1 to i=n−1 (π[0] just gets assigned with 0).		<br/><br/>
			2. To calculate the current value π[i] we set the variable j 	<br/>
					denoting the length of the best suffix for i−1. Initially j=π[i−1].	<br/>
			3. Test if the suffix of length j+1 is also a prefix by		 <br/><br/>
					comparing s[j] and s[i]. If they are equal then we assign π[i]=j+1, 	<br/>
					otherwise we reduce j to π[j−1] and repeat this step.		<br/><br/>
			4. If we have reached the length j=0 and still don't have a match,	<br/> 
					then we assign π[i]=0 and go to the next index i+1.		<br/><br/>
					
			@param
		 	pattern(String)
		***/
			private List<Integer> getPrefixTable(char[] pattern){
				
				List<Integer> prefixTable = new ArrayList<Integer>();
				int n = pattern.length;
				for(int i = 0; i < n; i++) {
					prefixTable.add(0);
				}
				
				for(int i = 1; i < n; i++) {
					for(int j = prefixTable.get(i - 1); j >= 0;) {
						if(pattern[j] == pattern[i]) {
							prefixTable.set(i, j + 1);
							break;
						}
						else if(j > 0){
							j = prefixTable.get(j - 1);
						}
						else {
							break;
						}
					}
				}
				
				return prefixTable;
			}
		}
		
	
	
		private static class Point {
			long x;
			long y;
			Point(long x, long y){
				this.x = x;
				this.y = y;
			}
			
			@Override
			public boolean equals(Object obj) {
				Point ob = (Point) obj;
				if(this.x == ob.x && this.y == ob.y){
					return true;
				}
				return false;
				
			}
			@Override
			public String toString() {
				return this.x + " " + this.y;
			}
			
			@Override
			public int hashCode() {
			    return 0;
			}
		}
	
		private static long pow(int base, int pow) {
			long val = 1L;
			for(int i = 1; i <= pow; i++) {
				val *= base;
			}
			return val;
		}
		
		private static int log(int x, int base) {
			return (int) (Math.log(x) / Math.log(base));
		}
		private static int log(long x, int base) {
			return (int) (Math.log(x) / Math.log(base));
		}
		private static long max(long a, long b) {
			if (a >= b) {
				return a;
			}
			return b;
		}
	
		private static long abs(long a) {
			if (a < 0) {
				return -a;
			}
			return a;
		}
	
		private static int abs(int a) {
			if (a < 0) {
				return -a;
			}
			return a;
		}
	
		private static int max(int a, int b) {
			if (a >= b) {
				return a;
			}
			return b;
		}
	
		private static int min(int a, int b) {
			if (a <= b) {
				return a;
			}
			return b;
		}
		
		private static long min(long a, long b) {
			if (a <= b) {
				return a;
			}
			return b;
		}
	
		private static long gcd(long a, long b) {
			if (b == 0) {
				return a;
			}
			return gcd(b, a % b);
		}
	
		private static int gcd(int a, int b) {
			if (b == 0) {
				return a;
			}
			return gcd(b, a % b);
		}
	
		private static long bigMod(long n, long k, long m) {
	
			long ans = 1;
			while (k > 0) {
				if ((k & 1) == 1) {
					ans = (ans * n) % m;
				}
				n = (n * n) % m;
				k >>= 1;
			}
			return ans;
		}
	
		/*
		 * Returns an iterator pointing to the first element in the range [first,
		 * last] which does not compare less than val.
		 * 
		 */
		private static int lowerBoundNew(long[] arr, long num) {
			int start = 0;
			int end = arr.length - 1;
			int index = 0;
			int len = arr.length;
			int mid = 0;
			while (true) {
				if (start > end) {
					break;
				}
				mid = (start + end) / 2;
				if (arr[mid] > num) {
					end = mid - 1;
				} else if (arr[mid] < num) {
					start = mid + 1;
				} else {
					while (mid >= 0 && arr[mid] == num) {
						mid--;
					}
					return mid + 1;
				}
			}
			if (arr[mid] < num) {
				return mid + 1;
			}
			return mid;
		}
	
		/*
		 * upper_bound() is a standard library function in C++ defined in the header
		 * . It returns an iterator pointing to the first element in the range
		 * [first, last) that is greater than value, or last if no such element is
		 * found
		 * 
		 */
		private static int upperBoundNew(long arr[], long num) {
	
			int start = 0;
			int end = arr.length - 1;
			int index = 0;
			int len = arr.length;
			int mid = 0;
			while (true) {
				if (start > end) {
					break;
				}
				mid = (start + end) / 2;
				long val = arr[mid];
				if (val > num) {
					end = mid - 1;
				} else if (val < num) {
					start = mid + 1;
				} else {
					while (mid < len && arr[mid] == num) {
						mid++;
					}
					if (mid == len - 1 && arr[mid] == num) {
						return mid + 1;
					} else {
						return mid;
					}
				}
			}
			if (arr[mid] < num) {
				return mid + 1;
			}
			return mid;
		}
	
		private static class InputReader {
			public BufferedReader reader;
			public StringTokenizer tokenizer;
	
			public InputReader(InputStream stream) {
				reader = new BufferedReader(new InputStreamReader(stream));
				tokenizer = null;
			}
	
			public String next() {
				try {
					while (tokenizer == null || !tokenizer.hasMoreTokens()) {
						tokenizer = new StringTokenizer(reader.readLine());
	
					}
				} catch (IOException e) {
					return null;
				}
				return tokenizer.nextToken();
			}
	
			public String nextLine() {
				String line = null;
				try {
					tokenizer = null;
					line = reader.readLine();
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
				return line;
			}
	
			public int nextInt() {
				return Integer.parseInt(next());
			}
	
			public double nextDouble() {
				return Double.parseDouble(next());
			}
	
			public long nextLong() {
				return Long.parseLong(next());
			}
	
			public boolean hasNext() {
				try {
					while (tokenizer == null || !tokenizer.hasMoreTokens()) {
						tokenizer = new StringTokenizer(reader.readLine());
					}
				} catch (Exception e) {
					return false;
				}
				return true;
			}
		}
	}