给定范围[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