📌  相关文章
📜  计数范围内的数字,偶数和奇数位置的数字总和为质数

📅  最后修改于: 2021-06-27 01:08:22             🧑  作者: Mango

给定范围[L,R] 。任务是计算在偶数位置的位数之和与奇数位置的位数之和为质数的范围内的数字。将数字中最低有效数字的位置视为一个奇数位置。

例子:

Input : L = 1, R = 50
Output : 6
Explanation : Only, 20, 30, 31, 41, 
42 and 50 are valid numbers. 

Input : L = 50, R = 100
Output : 18

先决条件: Digit DP

方法:首先,如果我们能够计算所需的数字,直到R,即在[0,R]范围内,则可以通过求解从零到R的值,然后减去,可以很容易地在[L,R]范围内得出答案。从零到L – 1求解后得到的答案。现在,我们需要定义DP状态。

DP州:

  • 由于我们可以将数字视为数字序列,因此一种状态是我们当前所处的位置。如果我们处理的数字最大为10 18,那么此位置的值可以为0到18 。在每个递归调用中,我们尝试通过从0到9放置一个数字来从左到右构建序列。
  • 第一状态是到目前为止我们放置的偶数位的数字总和
  • 第二种状态是到目前为止我们放在奇数位置的数字总和
  • 另一个状态是布尔变量tight ,它指示我们要构建的数字已经小于R,因此在接下来的递归调用中,我们可以将0到9之间的任何数字放置。如果数字没有变小,则为最大限制我们可以放置的位数是R中当前位置的位数。

同样,当我们达到基本条件时,我们需要检查所需的差值是否为质数。由于范围中的最大数字为10 18 ,所以偶数或奇数位置的最大和最大为9乘以9,因此最大差值为9。因此,在基本条件下,我们只需要检查最多不超过100的质数。

下面是上述方法的实现:

C++
// C++ implementation of the above approach
  
#include 
using namespace std;
  
const int M = 18;
int a, b, dp[M][90][90][2];
  
// Prime numbers upto 100
int prime[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23,
                29, 31, 37, 43, 47, 53, 59, 61, 
                67, 71, 73, 79, 83, 89, 97 };
  
// Function to return the count of
// required numbers from 0 to num
int count(int pos, int even, int odd, int tight,
        vector num)
{
    // Base Case
    if (pos == num.size()) {
        if (num.size() & 1)
            swap(odd, even);
        int d = even - odd;
  
        // check if the difference is equal
        // to any prime number
        for (int i = 0; i < 24; i++)
            if (d == prime[i])
                return 1;
                  
        return 0;
    }
  
    // If this result is already computed
    // simply return it
    if (dp[pos][even][odd][tight] != -1)
        return dp[pos][even][odd][tight];
  
    int ans = 0;
  
    // Maximum limit upto which we can place
    // digit. If tight is 1, means number has
    // already become smaller so we can place
    // any digit, otherwise num[pos]
    int limit = (tight ? 9 : num[pos]);
  
    for (int d = 0; d <= limit; d++) {
        int currF = tight, currEven = even;
        int currOdd = odd;
          
        if (d < num[pos])
            currF = 1;
  
        // If the current position is odd
        // add it to currOdd, otherwise to
        // currEven
        if (pos & 1)
            currOdd += d;
        else
            currEven += d;
              
        ans += count(pos + 1, currEven, currOdd,
                    currF, num);
    }
      
    return dp[pos][even][odd][tight] = ans;
}
  
// Function to convert x into its digit vector
// and uses count() function to return the
// required count
int solve(int x)
{
    vector num;
      
    while (x) {
        num.push_back(x % 10);
        x /= 10;
    }
      
    reverse(num.begin(), num.end());
  
    // Initialize dp
    memset(dp, -1, sizeof(dp));
    return count(0, 0, 0, 0, num);
}
  
// Driver Code
int main()
{
    int L = 1, R = 50;
    cout << solve(R) - solve(L - 1) << endl;
  
    L = 50, R = 100;
    cout << solve(R) - solve(L - 1) << endl;
      
    return 0;
}


Java
// Java implementation of the above approach 
import java.util.*;
  
class GFG
{
  
static int M = 18; 
static int a, b, dp[][][][] = new int[M][90][90][2]; 
  
// Prime numbers upto 100 
static int prime[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 
                29, 31, 37, 43, 47, 53, 59, 61, 
                67, 71, 73, 79, 83, 89, 97 }; 
  
// Function to return the count of 
// required numbers from 0 to num 
static int count(int pos, int even, int odd, int tight, 
        Vector num) 
{ 
    // Base Case 
    if (pos == num.size()) 
    { 
        if ((num.size() & 1) != 0)
        { 
            int t = odd;
            odd = even;
            even = t;
              
        }
        int d = even - odd; 
  
        // check if the difference is equal 
        // to any prime number 
        for (int i = 0; i < 24; i++) 
            if (d == prime[i]) 
                return 1; 
                  
        return 0; 
    } 
  
    // If this result is already computed 
    // simply return it 
    if (dp[pos][even][odd][tight] != -1) 
        return dp[pos][even][odd][tight]; 
  
    int ans = 0; 
  
    // Maximum limit upto which we can place 
    // digit. If tight is 1, means number has 
    // already become smaller so we can place 
    // any digit, otherwise num[pos] 
    int limit = (tight != 0 ? 9 : num.get(pos)); 
  
    for (int d = 0; d <= limit; d++) 
    { 
        int currF = tight, currEven = even; 
        int currOdd = odd; 
          
        if (d < num.get(pos)) 
            currF = 1; 
  
        // If the current position is odd 
        // add it to currOdd, otherwise to 
        // currEven 
        if ((pos & 1) != 0) 
            currOdd += d; 
        else
            currEven += d; 
              
        ans += count(pos + 1, currEven, currOdd, 
                    currF, num); 
    } 
      
    return dp[pos][even][odd][tight] = ans; 
} 
  
// Function to convert x into its digit vector 
// and uses count() function to return the 
// required count 
static int solve(int x) 
{ 
    Vector num = new Vector(); 
      
    while (x != 0) 
    { 
        num.add(x % 10); 
        x /= 10; 
    } 
      
    Collections.reverse(num); 
  
    // Initialize dp 
    for(int i = 0; i < dp.length; i++)
        for(int j = 0; j < dp[i].length; j++)
            for(int k = 0; k < dp[i][j].length; k++)
                for(int k1 = 0; k1 < dp[i][j][k].length; k1++)
                    dp[i][j][k][k1] = -1;
      
    return count(0, 0, 0, 0, num); 
} 
  
// Driver Code 
public static void main(String args[]) 
{ 
    int L = 1, R = 50; 
    System.out.println( solve(R) - solve(L - 1)); 
  
    L = 50; R = 100; 
    System.out.println( solve(R) - solve(L - 1)); 
} 
}
  
// This code is contributed by Arnab Kundu


Python3
# Python implementation of the above approach
  
M = 18
  
# Prime numbers upto 100
prime = [ 2, 3, 5, 7, 11, 13, 17, 19, 23,
        29, 31, 37, 43, 47, 53, 59, 61,
        67, 71, 73, 79, 83, 89, 97 ]
  
# Function to return the count of
# required numbers from 0 to num
def count(pos, even, odd, tight, num):
  
    # Base Case
    if pos == len(num):
        if len(num) & 1:
            odd, even = even, odd
  
        d = even - odd
  
        # check if the difference is equal
        # to any prime number
        for i in range(24):
            if d == prime[i]:
                return 1
        return 0
  
    # If this result is already computed
    # simply return it
    if dp[pos][even][odd][tight] != -1:
        return dp[pos][even][odd][tight]
  
    ans = 0
  
    # Maximum limit upto which we can place
    # digit. If tight is 1, means number has
    # already become smaller so we can place
    # any digit, otherwise num[pos]
    limit = 9 if tight else num[pos]
  
    for d in range(limit + 1):
        currF = tight
        currEven = even
        currOdd = odd
  
        if d < num[pos]:
            currF = 1
  
        # If the current position is odd
        # add it to currOdd, otherwise to
        # currEven
        if pos & 1:
            currOdd += d
        else:
            currEven += d
  
        ans += count(pos + 1, currEven, currOdd, currF, num)
  
    dp[pos][even][odd][tight] = ans
    return dp[pos][even][odd][tight]
  
# Function to convert x into its digit vector
# and uses count() function to return the
# required count
def solve(x):
    global dp
    num = []
    while x:
        num.append(x % 10)
        x //= 10
  
    num.reverse()
  
    # Initialize dp
    dp = [[[[-1, -1] for i in range(90)] 
            for j in range(90)] for k in range(M)]
    return count(0, 0, 0, 0, num)
  
# Driver Code
if __name__ == "__main__":
    dp = []
  
    L = 1
    R = 50
    print(solve(R) - solve(L - 1))
  
    L = 50
    R = 100
    print(solve(R) - solve(L - 1))
  
# This code is contributed by
# sanjeev2552


C#
// C# implementation of the above approach 
using System;
using System.Collections.Generic; 
  
class GFG
{
static int M = 18; 
static int a, b;
static int [,,,]dp = new int[M, 90, 90, 2]; 
  
// Prime numbers upto 100 
static int []prime = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 
                       29, 31, 37, 43, 47, 53, 59, 61, 
                       67, 71, 73, 79, 83, 89, 97 }; 
  
// Function to return the count of 
// required numbers from 0 to num 
static int count(int pos, int even, 
                 int odd, int tight,
                 List num) 
{ 
    // Base Case 
    if (pos == num.Count) 
    { 
        if ((num.Count & 1) != 0)
        { 
            int t = odd;
            odd = even;
            even = t;
              
        }
          
        int d = even - odd; 
  
        // check if the difference is equal 
        // to any prime number 
        for (int i = 0; i < 24; i++) 
            if (d == prime[i]) 
                return 1; 
                  
        return 0; 
    } 
  
    // If this result is already computed 
    // simply return it 
    if (dp[pos, even, odd, tight] != -1) 
        return dp[pos, even, odd, tight]; 
  
    int ans = 0; 
  
    // Maximum limit upto which we can place 
    // digit. If tight is 1, means number has 
    // already become smaller so we can place 
    // any digit, otherwise num[pos] 
    int limit = (tight != 0 ? 9 : num[pos]); 
  
    for (int d = 0; d <= limit; d++) 
    { 
        int currF = tight, currEven = even; 
        int currOdd = odd; 
          
        if (d < num[pos]) 
            currF = 1; 
  
        // If the current position is odd 
        // add it to currOdd, otherwise to 
        // currEven 
        if ((pos & 1) != 0) 
            currOdd += d; 
        else
            currEven += d; 
              
        ans += count(pos + 1, currEven, 
                     currOdd, currF, num); 
    } 
      
    return dp[pos, even, odd, tight] = ans; 
} 
  
// Function to convert x into its digit vector 
// and uses count() function to return the 
// required count 
static int solve(int x) 
{ 
    List num = new List(); 
      
    while (x != 0) 
    { 
        num.Add(x % 10); 
        x /= 10; 
    } 
      
    num.Reverse(); 
  
    // Initialize dp 
    for(int i = 0; i < dp.GetLength(0); i++)
        for(int j = 0; j < dp.GetLength(1); j++)
            for(int k = 0; k < dp.GetLength(2); k++)
                for(int k1 = 0; k1 < dp.GetLength(3); k1++)
                    dp[i, j, k, k1] = -1;
      
    return count(0, 0, 0, 0, num); 
} 
  
// Driver Code 
public static void Main(String []args) 
{ 
    int L = 1, R = 50; 
    Console.WriteLine(solve(R) - solve(L - 1)); 
  
    L = 50; R = 100; 
    Console.WriteLine(solve(R) - solve(L - 1)); 
} 
}
  
// This code is contributed by Rajput-Ji


输出:
6
18

如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。