[L, R] 范围内的整数计数,每个数字的频率为偶数
给定两个整数L和R ,任务是找到[L, R]范围内的整数计数,使得整数中每个数字的频率是偶数。
例子:
Input: L = 47, R = 999
Output: 5
Explanation: The integers that are in range [47, 999] and follow the given condition are {55, 66, 77, 88, 99}.
Input: L = 32, R = 1010
Output: 9
Explanation: The integers that are in range [32, 1010] and follow the given condition are {33, 44, 55, 66, 77, 88, 99, 1001, 1010}.
方法:上述问题可以借助位掩码和动态规划来解决。以下是一些可用于解决给定问题的观察结果:
- 具有 10 位的位掩码可用于存储[0, 9]范围内每个数字的奇偶校验,其中第 i个设置位将表示整数中数字i的频率为奇数。
- 让我们定义一个函数countInt(X)来查找[1, X]范围内的有效整数的计数。因此,范围[L, R]的答案可以计算为countInt(R) – countInt(L-1) 。
考虑一个 4D 数组,例如dp[][][][] ,其中dp[mask][length][smaller][started] ,其中mask表示 Bitmask 表示从0到9的每个数字的奇偶校验, length表示总当前数字中的位数,较小表示当前数字是否小于上限,即位于给定范围内,并且开始将跟踪由于前导零而导致的重复数字。以下是要遵循的步骤:
- 创建一个递归函数来遍历整数的每个索引,并为整数当前索引处的每个有效数字递归调用该函数。
- 跟踪变量中的前导零,以防止它们在计数中重复。
- 如果当前索引是最重要的索引,则有效数字必须在[1, 9]范围内,否则它们可以在[0, 9]范围内。
- 如果将数字放入整数的当前索引后,则当前数字是有效数字,形成整数 <= 范围的上限。
- 记忆每个状态的计数,如果当前状态已经计算,则返回记忆值。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Stores the upper limit of the range
string s;
// Stores the overlapping states
int dp[1024][10][2][2];
// Recursive Function to calculate the
// count of valid integers in the range
// [1, s] using memoization
int calcCnt(int mask, int len,
int smaller, int started)
{
// Base Case
if (len == s.size()) {
// If current integer has even
// count of digits and is not
// repeated
return (mask == 0 && started);
}
// If current state is already
// considered
if (dp[mask][len][smaller][started] != -1)
return dp[mask][len][smaller][started];
// Stores the maximum valid digit at
// the current index
int mx = 9;
if (!smaller) {
mx = s[len] - '0';
}
// Stores the count of valid integers
int ans = 0;
// If the current digit is not the
// most significant digit, i.e, the
// integer is already started
if (started) {
// Iterate through all valid digits
for (int i = 0; i <= mx; i++) {
// Recursive call for ith digit
// at the current index
ans += calcCnt(mask ^ (1 << i), len + 1,
smaller || (i < s[len] - '0'), 1);
}
}
else {
// Recursive call for integers having
// leading zeroes in the beginning
ans = calcCnt(mask, len + 1, 1, 0);
// Iterate through all valid digits as
// most significant digits
for (int i = 1; i <= mx; i++) {
// Recursive call for ith digit
// at the current index
ans += calcCnt(mask ^ (1 << i), len + 1,
smaller || (i < s[len] - '0'), 1);
}
}
// Return answer
return dp[mask][len][smaller][started] = ans;
}
// Function to calculate valid number in
// the range [1, X]
int countInt(int x)
{
// Initialize dp array with -1
memset(dp, -1, sizeof(dp));
// Store the range in form of string
s = to_string(x);
// Return Count
return calcCnt(0, 0, 0, 0);
}
// Function to find the count of integers
// in the range [L, R] such that the
// frequency of each digit is even
int countIntInRange(int L, int R)
{
return countInt(R) - countInt(L - 1);
}
// Driver Code
int main()
{
int L = 32, R = 1010;
cout << countIntInRange(L, R);
return 0;
}
Java
// Java program for the above approach
import java.util.*;
class GFG{
// Stores the upper limit of the range
static String s;
// Stores the overlapping states
static int [][][][] dp = new int[1024][10][2][2];
// Function to convert Integer to boolean
static boolean toBoolean(int smaller)
{
if (smaller >= 1)
return true;
else
return false;
}
// Recursive Function to calculate the
// count of valid integers in the range
// [1, s] using memoization
static int calcCnt(int mask, int len,
int smaller, int started)
{
// Base Case
if (len == s.length()) {
// If current integer has even
// count of digits and is not
// repeated
if (mask == 0 && started !=0)
return 1;
else
return 0;
}
// If current state is already
// considered
if (dp[mask][len][smaller][started] != -1)
return dp[mask][len][smaller][started];
// Stores the maximum valid digit at
// the current index
int mx = 9;
if (smaller == 0) {
mx = (int)s.charAt(len) - 48;
}
// Stores the count of valid integers
int ans = 0;
// If the current digit is not the
// most significant digit, i.e, the
// integer is already started
if (started !=0) {
// Iterate through all valid digits
for (int i = 0; i <= mx; i++) {
// Recursive call for ith digit
// at the current index
ans += calcCnt(mask ^ (1 << i), len + 1,
toBoolean(smaller) || (i < (int)s.charAt(len) - 48)?1:0,
1);
}
}
else {
// Recursive call for integers having
// leading zeroes in the beginning
ans = calcCnt(mask, len + 1, 1, 0);
// Iterate through all valid digits as
// most significant digits
for (int i = 1; i <= mx; i++) {
// Recursive call for ith digit
// at the current index
ans += calcCnt(mask ^ (1 << i), len + 1,
toBoolean(smaller) || (i < (int)s.charAt(len) - 48)?1:0,
1);
}
}
// Return answer
dp[mask][len][smaller][started] = ans;
return ans;
}
// Function to calculate valid number in
// the range [1, X]
static int countInt(int x)
{
// Initialize dp array with -1
for(int i = 0; i < 1024; i++){
for(int j = 0; j < 10; j++){
for(int k = 0; k < 2; k++){
for(int l = 0; l < 2; l++)
dp[i][j][k][l] = -1;
}
}
}
// Store the range in form of string
s = Integer.toString(x);
// Return Count
return calcCnt(0, 0, 0, 0);
}
// Function to find the count of integers
// in the range [L, R] such that the
// frequency of each digit is even
static int countIntInRange(int L, int R)
{
return countInt(R) - countInt(L - 1);
}
// Driver Code
public static void main(String [] args)
{
int L = 32, R = 1010;
System.out.println(countIntInRange(L, R));
}
}
// This code is contributed by ihritik
Python3
# Python program for the above approach
# Stores the upper limit of the range
s = ""
# Stores the overlapping states
dp = [[[[0 for _ in range(2)] for _ in range(2)]
for _ in range(10)] for _ in range(1024)]
# Recursive Function to calculate the
# count of valid integers in the range
# [1, s] using memoization
def calcCnt(mask, sz, smaller, started):
# Base Case
if (sz == len(s)):
# If current integer has even
# count of digits and is not
# repeated
return (mask == 0 and started)
# If current state is already
# considered
if (dp[mask][sz][smaller][started] != -1):
return dp[mask][sz][smaller][started]
# Stores the maximum valid digit at
# the current index
mx = 9
if (not smaller):
mx = ord(s[sz]) - ord('0')
# Stores the count of valid integers
ans = 0
# If the current digit is not the
# most significant digit, i.e, the
# integer is already started
if (started):
# Iterate through all valid digits
for i in range(0, mx+1):
# Recursive call for ith digit
# at the current index
ans += calcCnt(mask ^ (1 << i), sz + 1,
smaller or (i < ord(s[sz]) - ord('0')), 1)
else:
# Recursive call for integers having
# leading zeroes in the beginning
ans = calcCnt(mask, sz + 1, 1, 0)
# Iterate through all valid digits as
# most significant digits
for i in range(1, mx+1):
# Recursive call for ith digit
# at the current index
ans += calcCnt(mask ^ (1 << i), sz + 1,
smaller or (i < ord(s[sz]) - ord('0')), 1)
# Return answer
dp[mask][sz][smaller][started] = ans
return dp[mask][sz][smaller][started]
# Function to calculate valid number in
# the range [1, X]
def countInt(x):
# Initialize dp array with -1
global dp
dp = [[[[-1 for _ in range(2)] for _ in range(2)]
for _ in range(10)] for _ in range(1024)]
# Store the range in form of string
global s
s = str(x)
# Return Count
return calcCnt(0, 0, 0, 0)
# Function to find the count of integers
# in the range [L, R] such that the
# frequency of each digit is even
def countIntInRange(L, R):
return countInt(R) - countInt(L - 1)
# Driver Code
if __name__ == "__main__":
L = 32
R = 1010
print(countIntInRange(L, R))
# This code is contributed by rakeshsahni
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG{
// Stores the upper limit of the range
static string s;
// Stores the overlapping states
static int [,,,]dp = new int[1024, 10, 2, 2];
// Recursive Function to calculate the
// count of valid integers in the range
// [1, s] using memoization
static int calcCnt(int mask, int len,
int smaller, int started)
{
// Base Case
if (len == s.Length) {
// If current integer has even
// count of digits and is not
// repeated
if (mask == 0 && started !=0)
return 1;
else
return 0;
}
// If current state is already
// considered
if (dp[mask, len, smaller, started] != -1)
return dp[mask, len, smaller, started];
// Stores the maximum valid digit at
// the current index
int mx = 9;
if (smaller == 0) {
mx = (int)s[len] - 48;
}
// Stores the count of valid integers
int ans = 0;
// If the current digit is not the
// most significant digit, i.e, the
// integer is already started
if (started !=0) {
// Iterate through all valid digits
for (int i = 0; i <= mx; i++) {
// Recursive call for ith digit
// at the current index
ans += calcCnt(mask ^ (1 << i), len + 1,
Convert.ToBoolean(smaller) || (i < (int)s[len] - 48)?1:0,
1);
}
}
else {
// Recursive call for integers having
// leading zeroes in the beginning
ans = calcCnt(mask, len + 1, 1, 0);
// Iterate through all valid digits as
// most significant digits
for (int i = 1; i <= mx; i++) {
// Recursive call for ith digit
// at the current index
ans += calcCnt(mask ^ (1 << i), len + 1,
Convert.ToBoolean(smaller) || (i < (int)s[len] - 48)?1:0,
1);
}
}
// Return answer
dp[mask, len, smaller, started] = ans;
return ans;
}
// Function to calculate valid number in
// the range [1, X]
static int countInt(int x)
{
// Initialize dp array with -1
for(int i = 0; i < 1024; i++){
for(int j = 0; j < 10; j++){
for(int k = 0; k < 2; k++){
for(int l = 0; l < 2; l++)
dp[i, j, k, l] = -1;
}
}
}
// Store the range in form of string
s = x.ToString();
// Return Count
return calcCnt(0, 0, 0, 0);
}
// Function to find the count of integers
// in the range [L, R] such that the
// frequency of each digit is even
static int countIntInRange(int L, int R)
{
return countInt(R) - countInt(L - 1);
}
// Driver Code
public static void Main()
{
int L = 32, R = 1010;
Console.Write(countIntInRange(L, R));
}
}
// This code is contributed by ipg2016107.
输出:
9
时间复杂度:
辅助空间: