Problem:
Problem F: Find the Multiples

You are given a sequence a0a1...aN-1 digits and a prime number Q. For each i ≤ j with ai ≠ 0, the subsequence aiai+1...aj can be read as a decimal representation of a positive integer. Subsequences with leading zeros are not considered. Your task is to count the number of pairs (i, j) such that the corresponding subsequence is a multiple of Q.

Input

The input consists of at most 50 datasets. Each dataset is represented by a line containing four integers N, S, W, and Q, separated by spaces, where 1 ≤ N ≤ 105, 1 ≤ S ≤ 109, 1 ≤ W ≤ 109, and Q is a prime number less than 108. The sequence a0...aN-1 of length N is generated by the following code, in which ai is written as a[i].

int g = S;
for(int i=0; i<N; i++) {
a[i] = (g/7) % 10;
if( g%2 == 0 ) { g = (g/2); }
else { g = (g/2) ^ W; }
}

Note: the operators /, %, and ^ are the integer division, the modulo, and the bitwise exclusiveor, respectively. The above code is meant to be a random number generator. The intended solution does not rely on the way how the sequence is generated.

The end of the input is indicated by a line containing four zeros separated by spaces.

Output

For each dataset, output the answer in a line. You may assume that the answer is less than 230.

Sample Input

3 32 64 7
4 35 89 5
5 555 442 3
5 777 465 11
100000 666 701622763 65537
0 0 0 0

Output for the Sample Input

2
4
6
3
68530

In the first dataset, the sequence is 421. We can find two multiples of Q = 7, namely, 42 and 21.

In the second dataset, the sequence is 5052, from which we can find 5, 50, 505, and 5 being the multiples of Q = 5. Notice that we don't count 0 or 05 since they are not a valid representation of positive integers. Also notice that we count 5 twice, because it occurs twice in different positions.

In the third and fourth datasets, the sequences are 95073 and 12221, respectively.

Solution in JAVA (judge verdict: Accepted)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;

public class Main {
	static FastScanner sc = new FastScanner();
	static int N, Q;
	static int[][] key = new int[512][512];
	static int[][] val = new int[512][512];
	static Reader input = new BufferedReader(new InputStreamReader(System.in));

	public static void main(String[] args) throws Exception {
		StringBuilder sb = new StringBuilder();
		int[] A = new int[100000];
		while (true) {
			N = sc.nextInt();
			if (N == 0) break;
			int S = sc.nextInt();
			int W = sc.nextInt();
			Q = sc.nextInt();
			int g = S;
			for (int i = 0; i < N; ++i) {
				A[i] = (g / 7) % 10;
				g = (g / 2) ^ (W * (g % 2));
			}
			sb.append(solve(A) + "\n");
		}
		System.out.print(sb);
	}

	static long solve(int[] A) {
		long ans = 0;
		if (Q == 2 || Q == 5) {
			int nonzero = 0;
			for (int i = 0; i < N; ++i) {
				if (A[i] != 0) ++nonzero;
				if (A[i] % Q == 0) {
					ans += nonzero;
				}
			}
			return ans;
		}
		for (int i = 0; i < key.length; ++i) {
			for (int j = 0; val[i][j] != 0; ++j) {
				val[i][j] = 0;
			}
		}

		long sum = 0;
		long base = 1;
		for (int i = 0; i < N; ++i) {
			sum += A[N - 1 - i] * base;
			while (sum >= Q) {
				sum -= Q;
			}
			base *= 10;
			while (base >= Q) {
				base -= Q;
			}
			int c = 0;
			int k = (int) (sum & 511);
			for (int j = 0;; ++j) {
				if (val[k][j] == 0) {
					key[k][j] = (int) sum;
					val[k][j] = 1;
					break;
				}
				if (key[k][j] == (int) sum) {
					c = val[k][j];
					val[k][j]++;
					break;
				}
			}
			if (A[N - 1 - i] != 0) {
				ans += c;
				if (sum == 0) ans++;
			}
		}
		return ans;
	}

	static class FastScanner {
		Reader input;

		FastScanner() {
			this.input = new BufferedReader(new InputStreamReader(System.in));
		}

		int nextInt() throws IOException {
			int sign = 1;
			int b = input.read();
			while ((b < '0' || '9' < b) && b != '-' && b != '+') {
				b = input.read();
			}
			if (b == '-') {
				sign = -1;
				b = input.read();
			} else if (b == '+') {
				b = input.read();
			}
			int ret = b - '0';
			while (true) {
				b = input.read();
				if (b < '0' || '9' < b) return ret * sign;
				ret *= 10;
				ret += b - '0';
			}
		}
	}

}