CareerCup Find the no. of expressions that evaluate to a Walprime

来源:互联网 发布:java测试用例怎么写 编辑:程序博客网 时间:2024/05/21 09:37
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: 

011 
12345 
Output: 

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) - 

For the second data set (10 points) - 

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);}



0 0
原创粉丝点击