给定两个整数L和R ,任务是计算范围[L, R]中所有数字之和为素数的数字。
例子:
Input: L = 1, R = 10
Output: 3
Explanation:
Numbers in the range L(= 1) to R(= 10), whose sum of digits is a prime number are {3, 5, 7}. Therefore, the required output is 3.
Input: L = 11, R = 999
Output: 336
朴素的方法:解决这个问题最简单的方法是遍历[L, R]范围内的所有数字,并对每个数字,检查该数字的数字之和是否为质数。如果发现为真,则增加计数,最后将计数打印为所需答案。
时间复杂度: O((R – L + 1) * sqrt(R))
辅助空间: O(1)
高效方法:该问题可以使用 Digit DP 解决。这个想法是计算范围[1, R]中数字和为素数的数字,并减去范围[1, L – 1]中数字和为素数的数字。以下是递推关系:
[Tex]= \sum^{9}_{i=0} cnt1XPrime(sum + i, len + 1, tight \& (i==end)) [/Tex]
cnt1XPrime(sum, len, tight): Stores the count of numbers in the range [1, X] with the following constraints:
sum= Stores sum of digits of a number in the range [1, X].
len = count of digits in X.
tight = Boolean value to check if the current digits range is restricted or not.
请按照以下步骤解决问题:
- 初始化一个 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];
// Initialize 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);
// Initialize 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];
// Initialize 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);
// Initialize 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)
# Initialize 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];
// Initialize 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);
// Initialize 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
Javascript
336
时间复杂度: O(sum * M * 10)
辅助空间: O(sum * M) ,其中sum表示[L, R]范围内数字的最大位数和M表示R 中的位数。
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。