Блог пользователя alpha_1001

Автор alpha_1001, история, 3 года назад, По-английски
Given a string **S** consisting of digits [0-9], count the number of ways this string can be split into continuous substrings such that each substring is a prime number. Each digit must be in one substring and the entire string must be used.

**Note:**
The input string does not contain leading zeros.
Each number split of the given number must be in the range `2 to 1e6` inclusive.
Since the answer can be large, return the answer modulo `1e9+7`.


**Constraints**
1 <= | S | <= 1e5

**Example**
_input_
11373
_output_
6
_Explanation_
[11, 3, 7, 3], [11, 3, 73], [11, 37, 3], [113, 7, 3], [113, 73], [11, 373].


Can anyone help me out?
Thanks in advance.
Happy Coding...
 
P.S.: This is my first blog, so correct me if I'm wrong anywhere.

Feel free to share your approach.

  • Проголосовать: нравится
  • -24
  • Проголосовать: не нравится

»
3 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Auto comment: topic has been updated by alpha_1001 (previous revision, new revision, compare).

»
3 года назад, # |
Rev. 2   Проголосовать: нравится +24 Проголосовать: не нравится

Is the question complete or any missing information/wrong constraints? Because how will you check the 100000 digit number is prime or not in a fast way?

»
3 года назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

I don't know about this problem but whenever the problem ask about count number of ways I always struck don't get in what direction should I think can somebody suggest me some good problem (rating<= 1700), on this topic
btw cool alpha_1001 nice problem
thanks for your suggestion -is-this-fft- i will try to solve some problem and keeping these things in mind

  • »
    »
    3 года назад, # ^ |
      Проголосовать: нравится +6 Проголосовать: не нравится

    "Count number of ways" is too broad, so it is really hard for anyone to suggest something.

    But being very comfortable with dynamic programming is always useful in such problems. In easier cases, the following will often solve the problem: let dp[i] be the number of ways to do something if we only consider the first i characters of the string (string can be replaced with whatever). Another thing that will help a lot is understanding the first principles of combinatorics: factorials, number of combinations and the like (not in this problem though).

»
3 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Auto comment: topic has been updated by alpha_1001 (previous revision, new revision, compare).

»
3 года назад, # |
  Проголосовать: нравится +26 Проголосовать: не нравится

Range DP. $$$dp[x]$$$ is the number of ways to split the number up until the $$$x$$$ part.

$$$dp[x] = \sum_{i = 1}^{7} dp[x - i] \text{ if the substring from x - i + 1 ... x is prime and in the range 2...1e6}.$$$

»
3 года назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится

You can use DP to solve this where dp[i] is the number of ways to split the substring [i, N] into primes. Ans is dp[1].

For each i, iterate j through [0, 5] and check if the substring [i, i+j] is prime. If it is prime, add dp[i+j+1] to dp[i].

Checking if a substring is prime can be done quickly O(1) using sieve of eratosthenes precomputation.

Total complexity: O(6*N + Mlog(M)) where M = 10^6 and the second term is for the prime precomputation

»
3 года назад, # |
Rev. 5   Проголосовать: нравится 0 Проголосовать: не нравится
from functools import lru_cache

def getPrimesUpTo(n):
    primes = set(range(2, n + 1))
    for i in range(2, n + 1):
        if i in primes:
            j = 2*i
            while j <= n:
                if j in primes:
                    primes.remove(j)
                j += i

    return primes

@lru_cache(None)
def helper(s, primes, i = 0, cur = None):
    # all primes that we split must be between 1 and 10**6
    if i == len(s):
        return 0 + (cur is None)

    cur = 0 if cur is None else cur
    cur = (cur * 10) + (ord(s[i]) - ord('0'))
    ret = 0
    if cur <= 10**6:
        ret += helper(s, primes, i + 1, cur)
    if cur in primes:
        ret += max(ret, helper(s, primes, i + 1, None))
    return ret % (10**9 + 7)

def countPrimeSplits(s):
    return helper(s, frozenset(getPrimesUpTo(10**6)))

Sieve to get the primes and apply DP to avoid redundant helper calls. The helper would be O(N^2) if not for the 10**6 limit, but it's more like O(N) with it.

I don't think frozenset is used very commonly — I definitely haven't used it before now — but it's useful in this case. I can't pass a regular set to that function because of the lru_cache decorator. It'd also be worth mentioning to the interviewer that we only have to run the sieve once before all of the function calls.

»
3 года назад, # |
  Проголосовать: нравится +65 Проголосовать: не нравится

you have used the wrong abbreviation for MANGA, 100 social credit has been deducted from your account

»
3 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Auto comment: topic has been updated by alpha_1001 (previous revision, new revision, compare).