📌  相关文章
📜  计算范围为[L,R]的数字,其数字总和为质数

📅  最后修改于: 2021-05-04 17:31:10             🧑  作者: Mango

给定两个整数LR ,任务是计算数字总和为质数的[L,R]范围内的所有数字。

例子:

天真的方法:解决此问题的最简单方法是遍历[L,R]范围内的所有数字,对于每个数字,请检查数字的总和是否为质数。如果发现是真的,则增加计数,最后将计数打印为所需的答案。

时间复杂度: O((R – L + 1)* sqrt(R))
辅助空间: O(1)

高效的方法:使用Digit DP可以解决该问题。想法是对数字总和为质数的[1,R]范围内的数字进行计数,然后将数字总和为质数的[1,L – 1]范围内的数字进行计数。以下是递归关系:

请按照以下步骤解决问题:

  • 初始化3D数组dp [sum] [len] [tight],以计算和存储上述递归关系的所有子问题的值。
  • 最后,返回dp [sum] [len] [tight]的值

下面是上述方法的实现:

C++
// C++ program to implement
// the above approach
 
#include 
using namespace std;
 
// Function to find all prime numbers
// in the range [1, 100000] using
// Sieve of Eratosthenes technique
vector sieve()
{
    // isPrime[i] stores if i
    // is a prime number or not.
    vector isPrime(100001,
                         true);
 
    // 0 is not a prime number
    isPrime[0] = false;
 
    // 1 is not prime number
    isPrime[1] = false;
 
    // Traverse the range to check if
    // i is a prime number or not
    for (int i = 2; i * i < 100001;
         i++) {
 
        // If i is a prime number
        if (isPrime[i]) {
            for (int j = i * i;
                 j < 100001; j += i) {
 
                // Mark its multiples non-prime
                isPrime[j] = false;
            }
        }
    }
 
    return isPrime;
}
 
// Function to count all numbers in
// the range[1, X] whose sum of digits
// is a prime number
int cnt1XPrime(int sum, int len, bool tight,
               string X, vector& isPrime,
               int dp[1000][100][2])
{
    // If count of digits in current number
    // is equal to the count of digits in X
    if (len == X.length()) {
 
        // If sum is a prime number
        return isPrime[sum];
    }
 
    // If already computed subproblem
    // occurred
    if (dp[sum][len][tight] != -1) {
        return dp[sum][len][tight];
    }
     
    // Stores maximum possible value
    // at current digit of the number
    int end = tight ? (X[len] - '0') : 9;
 
    // Stores count of numbers by placing
    // all possible values at current index
    int res = 0;
 
    // Place all possible values at
    // current position
    for (int i = 0; i <= end; i++) {
 
        // Update res
        res += cnt1XPrime(sum + i, len + 1,
                          (tight & (i == end)),
                          X, isPrime, dp);
    }
 
     dp[sum][len][tight]=res;
       return res;
}
 
// Function to count the numbers in
// the range[L, R]
int cntLRprime(int L, int R)
{
    // Stores the value of (L - 1)
    // in the form of string
    string LStr = to_string(L - 1);
 
    // Stores the value of (R)
    // in the form of string
    string RStr = to_string(R);
 
    // Stores values of overlapping
    // subproblems
    int dp[1000][100][2];
 
    // Initalize dp[][][] array
    memset(dp, -1, sizeof(dp));
 
    // isPrime[i] stores if i
    // is a prime number or not
    vector isPrime
        = sieve();
    // Stores count of numbers in range
    // [1, LStr] with the given conditions
    int cntL = cnt1XPrime(0, 0, 1, LStr,
                          isPrime, dp);
 
    // Initalize dp[][][] array.
    memset(dp, -1, sizeof(dp));
 
    // Stores count of numbers in range
    // [1, RStr] with the given conditions
    int cntR = cnt1XPrime(0, 0, 1, RStr,
                          isPrime, dp);
 
    // Return numbers in the range [L, R]
    // whose sum of digits is a prime number
    return (cntR - cntL);
}
 
// Driver Code
int main()
{
    int L = 11, R = 999;
    cout << cntLRprime(L, R);
 
    return 0;
}


Java
// Java program to implement
// the above approach
import java.util.*;
class solution {
 
    // Function to find all prime
    // numbers in the range [1, 100000]
    // using Sieve of Eratosthenes
    // technique
    static boolean[] sieve()
    {
        // isPrime[i] stores if i
        // is a prime number or not
        boolean[] isPrime = new boolean[100001];
 
        for (int i = 0; i < 100001; i++)
            isPrime[i] = true;
 
        // 0 is not a prime number
        isPrime[0] = false;
 
        // 1 is not prime number
        isPrime[1] = false;
 
        // Traverse the range to check if
        // i is a prime number or not
        for (int i = 2; i * i < 100001; i++) {
            // If i is a prime number
            if (isPrime[i] == true) {
                for (int j = i * i; j < 100001; j += i) {
                    // Mark its multiples
                    // non-prime
                    isPrime[j] = false;
                }
            }
        }
 
        return isPrime;
    }
 
    // Function to count all numbers in
    // the range[1, X] whose sum of digits
    // is a prime number
    static int cnt1XPrime(int sum, int len, int tight,
                          String X, boolean[] isPrime,
                          int[][][] dp)
    {
        // If count of digits in current
        // number is equal to the count of
        // digits in X
        if (len == X.length()) {
            // If sum is a prime number
            return isPrime[sum] ? 1 : 0;
        }
 
        // If already computed subproblem
        // occurred
        if (dp[sum][len][tight] != -1) {
            return dp[sum][len][tight];
        }
 
        // Stores maximum possible value
        // at current digit of the number
        int end = (tight == 1) ? (X.charAt(len) - 48) : 9;
 
        // Stores count of numbers by
        // placing all possible values
        // at current index
        int res = 0;
 
        // Place all possible values at
        // current position
        for (int i = 0; i <= end; i++) {
            // Update res
            res += cnt1XPrime(
                sum + i, len + 1,
                (tight & ((i == end) ? 1 : 0)), X, isPrime,
                dp);
        }
 
        return dp[sum][len][tight] = res;
    }
 
    // Function to count the numbers in
    // the range[L, R]
    static int cntLRprime(int L, int R)
    {
        // Stores the value of (L - 1)
        // in the form of string
        String LStr = String.valueOf(L - 1);
 
        // Stores the value of (R)
        // in the form of string
        String RStr = String.valueOf(R);
 
        // Stores values of overlapping
        // subproblems
        int[][][] dp = new int[1000][100][2];
 
        // Initalize dp[][][] array
        for (int i = 0; i < 1000; i++) {
            for (int j = 0; j < 100; j++) {
                for (int k = 0; k < 2; k++)
                    dp[i][j][k] = -1;
            }
        }
        // isPrime[i] stores if i
        // is a prime number or not
        boolean[] isPrime = sieve();
 
        // Stores count of numbers in
        // range [1, LStr] with the
        // given conditions
        int cntL = cnt1XPrime(0, 0, 1, LStr, isPrime, dp);
 
        // Initalize dp[][][] array.
        for (int i = 0; i < 1000; i++) {
            for (int j = 0; j < 100; j++) {
                for (int k = 0; k < 2; k++)
                    dp[i][j][k] = -1;
            }
        }
 
        // Stores count of numbers in range
        // [1, RStr] with the given conditions
        int cntR = cnt1XPrime(0, 0, 1, RStr, isPrime, dp);
 
        // Return numbers in the range
        // [L, R] whose sum of digits
        // is a prime number
        return (cntR - cntL);
    }
 
    // Driver Code
    public static void main(String args[])
    {
        int L = 11, R = 999;
        System.out.print(cntLRprime(L, R));
    }
}
 
// This code is contributed by SURENDRA_GANGWAR


Python3
# Python3 program to implement
# the above approach
isPrime = [True] * 100001
 
dp = [[[-1 for i in range(2)]
       for i in range(100)]
      for i in range(1000)]
 
# Function to find all prime numbers
# in the range [1, 100000] using
# Sieve of Eratosthenes technique
 
 
def sieve():
 
    # 0 is not a prime number
    isPrime[0] = False
 
    # 1 is not prime number
    isPrime[1] = False
 
    # Traverse the range to check if
    # i is a prime number or not
    for i in range(2, 100001):
        if i * i > 100001:
            break
 
        # If i is a prime number
        if (isPrime[i]):
            for j in range(i * i, 100001, i):
 
                # Mark its multiples non-prime
                isPrime[j] = False
 
# Function to count all numbers in
# the range[1, X] whose sum of digits
# is a prime number
 
 
def cnt1XPrime(sum, lenn, tight, X):
 
    # If count of digits in current number
    # is equal to the count of digits in X
    if (lenn == len(X)):
 
        # If sum is a prime number
        return isPrime[sum]
 
    # If already computed subproblem
    # occurred
    if (dp[sum][lenn][tight] != -1):
        return dp[sum][lenn][tight]
 
    # Stores maximum possible value
    # at current digit of the number
    end = 9
 
    if tight:
        end = ord(X[lenn]) - ord('0')
 
    # Stores count of numbers by placing
    # all possible values at current index
    res = 0
 
    # Place all possible values at
    # current position
    for i in range(end + 1):
 
        # Update res
        res += cnt1XPrime(sum + i,
                          lenn + 1,
                          (tight & (i == end)), X)
 
    return dp[sum][lenn][tight] = res
 
# Function to count the numbers in
# the range[L, R]
 
 
def cntLRprime(L, R):
 
    # Stores the value of (L - 1)
    # in the form of string
    LStr = str(L - 1)
 
    # Stores the value of (R)
    # in the form of string
    RStr = str(R)
 
    # isPrime[i] stores if i
    # is a prime number or not
    sieve()
 
    # Stores count of numbers in range
    # [1, LStr] with the given conditions
    cntL = cnt1XPrime(0, 0, 1, LStr)
 
    # Initalize dp[][][] array.
    for i in range(1000):
        for j in range(100):
            for z in range(2):
                dp[i][j][z] = -1
 
    # Stores count of numbers in range
    # [1, RStr] with the given conditions
    cntR = cnt1XPrime(0, 0, 1, RStr)
 
    # Return numbers in the range [L, R]
    # whose sum of digits is a prime number
    return (cntR - cntL)
 
 
# Driver code
if __name__ == '__main__':
 
    L = 11
    R = 999
 
    print(cntLRprime(L, R))
 
# This code is contributed by mohit kumar 29


C#
// C# program to implement
// the above approach
using System;
class GFG {
 
    // Function to find all prime
    // numbers in the range [1, 100000]
    // using Sieve of Eratosthenes
    // technique
    static bool[] sieve()
    {
        // isPrime[i] stores if i
        // is a prime number or not
        bool[] isPrime = new bool[100001];
 
        for (int i = 0; i < 100001; i++)
            isPrime[i] = true;
 
        // 0 is not a prime
        // number
        isPrime[0] = false;
 
        // 1 is not prime
        // number
        isPrime[1] = false;
 
        // Traverse the range to
        // check if i is a prime
        // number or not
        for (int i = 2; i * i < 100001; i++) {
            // If i is a prime number
            if (isPrime[i] == true) {
                for (int j = i * i; j < 100001; j += i) {
                    // Mark its multiples
                    // non-prime
                    isPrime[j] = false;
                }
            }
        }
 
        return isPrime;
    }
 
    // Function to count all numbers
    // in the range[1, X] whose sum
    // of digits is a prime number
    static int cnt1XPrime(int sum, int len, int tight,
                          String X, bool[] isPrime,
                          int[, , ] dp)
    {
        // If count of digits in current
        // number is equal to the count of
        // digits in X
        if (len == X.Length) {
            // If sum is a prime number
            return isPrime[sum] ? 1 : 0;
        }
 
        // If already computed
        // subproblem occurred
        if (dp[sum, len, tight] != -1) {
            return dp[sum, len, tight];
        }
 
        // Stores maximum possible value
        // at current digit of the number
        int end = (tight == 1) ? (X[len] - 48) : 9;
 
        // Stores count of numbers by
        // placing all possible values
        // at current index
        int res = 0;
 
        // Place all possible values at
        // current position
        for (int i = 0; i <= end; i++) {
            // Update res
            res += cnt1XPrime(
                sum + i, len + 1,
                (tight & ((i == end) ? 1 : 0)), X, isPrime,
                dp);
        }
 
        return dp[sum, len, tight] = res;
    }
 
    // Function to count the numbers in
    // the range[L, R]
    static int cntLRprime(int L, int R)
    {
        // Stores the value of (L - 1)
        // in the form of string
 
        string LStr = (L - 1).ToString();
 
        // Stores the value of (R)
        // in the form of string
        string RStr = (R).ToString();
 
        // Stores values of overlapping
        // subproblems
        int[, , ] dp = new int[1000, 100, 2];
 
        // Initalize dp[][][] array
        for (int i = 0; i < 1000; i++) {
            for (int j = 0; j < 100; j++) {
                for (int k = 0; k < 2; k++)
                    dp[i, j, k] = -1;
            }
        }
 
        // isPrime[i] stores if i
        // is a prime number or not
        bool[] isPrime = sieve();
 
        // Stores count of numbers in
        // range [1, LStr] with the
        // given conditions
        int cntL = cnt1XPrime(0, 0, 1, LStr, isPrime, dp);
 
        // Initalize dp[][][] array.
        for (int i = 0; i < 1000; i++) {
            for (int j = 0; j < 100; j++) {
                for (int k = 0; k < 2; k++)
                    dp[i, j, k] = -1;
            }
        }
 
        // Stores count of numbers in
        // range [1, RStr] with the
        // given conditions
        int cntR = cnt1XPrime(0, 0, 1, RStr, isPrime, dp);
 
        // Return numbers in the range
        // [L, R] whose sum of digits
        // is a prime number
        return (cntR - cntL);
    }
 
    // Driver Code
    public static void Main(String[] args)
    {
        int L = 11, R = 999;
        Console.Write(cntLRprime(L, R));
    }
}
 
// This code is contributed by Chitranayal


输出
336

时间复杂度: O(sum * M * 10)
辅助空间: O(sum * M) ,其中sum表示在[L,R]范围内的数字的最大位数之和, M表示R中的位数。