Engineers at Google have decided to call any integer (+ve, -ve or 0) that is divisible by at least one of the single digit primes (2, 3, 5, 7) as Walprimes. Thus -21, -30, 0, 5, 14 etc are Walprimes, while -121, 1, 143 etc. are not Walprimes.
Now, consider a n-digit integer d1d2d3..dn. Between any 2 consecutive digits you can place either a (+) sign, a (-) sign or nothing. So, there are 3n-1 different expressions that can be formed from it. Some of the expressions so formed may evaluate to a Walprime. For example, consider the 6 digit integer 123456: 1 + 234 - 5 + 6 = 236, which is a Walprime, but 123 + 4 - 56 = 71, which is not a Walprime.
Your task is to write a program to find the no. of expressions (out of the possible 3n-1 expressions) that evaluate to a Walprime, for a given input. Note that leading zeroes are valid. For example, if the input is 1202004, it can be split as 12 + 020 - 04 etc. Also, the input itself can contain leading zeroes.
Input format: (Read from stdin)
The first line of input contains a single integer 'T' denoting the no. of test cases.
Each of the following 'T' lines contain a single string 's' (of length 'n') denoting an input for which you need to find the no. of valid expressions evaluating to a Walprime.
Output format: (Write to stdout)
Output exactly 'T' integers (one per line), where the ith line denotes the no. of valid expressions that evaluate to a Walprime for the ith input string. Since the output can be large, print all the quantities modulo 1000000007.
Sample testcase:
Input:
2
011
12345
Output:
6
64
Explanation:
For the first test case, s = "011". There are 32 = 9 valid expressions that can be formed from this string, namely {0+11, 0-11, 0+1+1, 0+1-1, 0-1+1, 0-1-1, 01+1, 01-1, 011} . Out of these 9 expressions, only the following 6 of them evaluate to a Walprime: {0+1+1, 0+1-1, 0-1+1, 0-1-1, 01+1, 01-1}.
Constraints:
There are 3 data sets.
For the first data set (5 points) -
1
For the second data set (10 points) -
1
For the third data set (15 points) -
1
------------------------------------------------------------------------------------------------------------------------
We could use Inclusion–exclusion principle AND dynamic programming. The time complexity can be reduced to polynomial.
Firstly, Inclusion–exclusion principle:
Define F(s, p) to be the no. of expressions whose result are divisible by number p. For example, F("011", 2) = 6, F("011", 3) = 3.
Define F(s, {p, q}) to be the no. of expressions whose result are divisible by at least one of the digit prime in {p, q}.
Then, by Inclusion–exclusion principle, F(s, {p, q}) = F(s, p) + F(s, q) - F(s, p * q)
We have F(s, {2, 3, 5, 7}) = F(s, 2) + F(s, 3) + F(s, 5) + F(s, 7) - F(s, 2 * 3) - ... + F(s, 2 * 3 * 5) + ... - F(s, 2 * 3 * 5 * 7)
Now, we use dynamic programming to find F(s, p).
let s[i:]be the suffix string start at index i,
let n be the length of string s.
let num[i:j] be the number converted from substring s[i:j] inclusive.
Define R[i][j] be the no. of expressions which are formed from substring s[i:] and the remainder is j while mod p. (0 <= i < n, 0 <= j < p)
For example, s = "011", p = 2, R[1][0] is the no. of expressions formed from substring "11" and the remainder is 0 while they mod 2. R[1][0] = 2, since (1 + 1) % 2 = 0, (1 - 1) % 2 = 0, and R[1][1] = 1, since 11 % 2 = 1.
R[i][j] can be calculated from sub-problems R[k][l], where (num[i:k -1] + l) % p == j or (num[i: k - 1] - l) % p == j, for all k > i and k < n.
Then R[i][j] = Sum(R[k][(j - num[i:k - 1]) % p] +R[k][(num[i:k - 1] - j) % p], k = i + 1, ..., n - 1)
We get F(s, p) from R[0][0].
Here is code:
int F(const string& s, int p) {
int n = s.size(), R[n][p];
memset(R, 0, sizeof(R));
for (int i = n - 1; i >= 0; i--) {
int first = s[i] - '0';
for (int k = i + 1; k < n; k++) {
for (int j = 0; j < p; j++) {
// -1 % 2 = -1 replaced with (2 + -1 % 2) % 2 = 1
R[i][j] += R[k][(p + (j - first) % p) % p];
R[i][j] += R[k][(p + (first - j) % p) % p];
}
first = 10 * first + s[k] - '0';
}
R[i][first % p] += 1;
}
return R[0][0];
}
int walprimes(const string& s) {
return F(s, 2) + F(s, 3) + F(s, 5) + F(s, 7)
- F(s, 2 * 3) - F(s, 2 * 5) - F(s, 2 * 7) - F(s, 3 * 5) - F(s, 3 * 7) - F(s, 5 * 7)
+ F(s, 3 * 5 * 7) + F(s, 2 * 5 * 7) + F(s, 2 * 3 * 7) + F(s, 2 * 3 * 5)
- F(s, 2 * 3 * 5 * 7);
}