📜  奇数个偶数和偶数个奇数范围内的整数计数

📅  最后修改于: 2021-04-29 07:15:27             🧑  作者: Mango

给定范围[L,R] ,任务是计算具有奇数个偶数和偶数个奇数的数字。例如,

  1. 8具有1个偶数和0个奇数–满足条件,因为1为奇数,0为偶数。
  2. 545具有1个偶数和2个奇数–满足条件,因为1是奇数,而2是偶数。
  3. 4834具有3个偶数和1个奇数–由于奇数有奇数(即1),因此不满足条件。

例子:

方法:

  • 情况1
    在这些数字之间存在一种模式1  10^{k}  (其中1 <= k <= 18)。
    来自的次数
    • 1 – 10和1 – 100是4
    • 1 – 1000和1 – 10000是454
    • 1 – 10000和1 – 100000是45454
  • 情况二
    • 如果数字中的位数是偶数,则它不能满足给定条件,因为我们需要一个奇数(个数)和一个偶数(个数)来满足我们的条件,并且奇数+偶数始终是奇数
    • 因此,如果给定数字(例如n)的位数是偶数,则它的出现次数从1开始等于1  到最大10^{k}  (1 <= k <= 18)小于n
  • 情况3
    如果给定数字(例如n)的位数是奇数,则两次之间的出现次数10^{k}+1  并且n等于

在哪里10^{i}  是最大的10^{k}  小于n。

实现:现在我们现在如何计算从1到给定n的出现次数。所以,
从L到R的出现次数= NumberOfOccurrencesUpto(R)– NumberOfOccurrencesUpto(L – 1),其中L不等于1。

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
 
#define ll long long
 
// Pattern table from Case 1
map values{{1, 0},
                   {10, 4},
                   {100, 4},
                   {1000, 454},
                   {10000, 454},
                   {100000, 45454},
                   {1000000, 45454},
                   {10000000, 4545454},
                   {100000000, 4545454},
                   {1000000000, 454545454},
                   {10000000000, 454545454},
                   {100000000000, 45454545454},
                   {1000000000000, 45454545454},
                   {10000000000000, 4545454545454},
                   {100000000000000, 4545454545454},
                   {1000000000000000, 454545454545454},
                   {10000000000000000, 454545454545454},
                   {100000000000000000, 45454545454545454},
                   {1000000000000000000, 45454545454545454}};
 
// Function that returns the number of
// even and odd digits in val
pair count_even_odd(ll val)
{
    ll even = 0, odd = 0;
    while (val)
    {
        ll num = val % 10;
        if (num % 2 == 0)
            even++;
        else
            odd++;
        val /= 10;
    }
    return make_pair(even, odd);
}
 
// Function that returns True if num
// satisfies the given condition
bool satisfies_condition(ll num)
{
    pair answer = count_even_odd(num);
    ll even = answer.first;
    ll odd = answer.second;
 
    if (even % 2 == 1 and
         odd % 2 == 0) return true;
    return false;
}
 
// Function to return the count of
// numbers from 1 to val that
// satisfies the given condition
ll count_upto(ll val)
{
    // If the value is already present
    // in the values dict
    if (values.find(val) != values.end())
        return values[val];
 
    ll index = 1;
    for (int i = 0;
             i < to_string(val).length() - 1;
             i++)
         index *= 10;
 
    // If the value is even
    // Case 2
    if (to_string(val).length() % 2 == 0)
        return values[index];
 
    ll val_len = to_string(val).length();
    ll cnt = values[index];
 
    // Now the problem is to count the desired
    // numbers from 10**(val_len-1) + 1 to val
    ll left_end = index + 1;
 
    // Case 3
    // Eliminating all the even numbers
    cnt += (val - left_end) / 2;
    if (satisfies_condition(val) or
        satisfies_condition(left_end))
        cnt++;
 
    return cnt;
}
 
// Driver Code
int main()
{
    // Input l and r
    ll l = 123, r = 984;
    ll right = count_upto(r);
    ll left = 0;
 
    if (l == '1')
        left = 0;
    else
        left = count_upto(l - 1);
 
    cout << right - left << endl;
    return 0;
}
 
// This code is contributed by
// sanjeev2552


Java
// Java implementation of the approach
import java.io.*;
import java.lang.*;
import java.util.*;
 
class GFG{
 
// Pattern table from Case 1
static HashMap values = new HashMap<>();
 
public static void intitializeMap()
{
    values = new HashMap<>();
    values.put(1L, 0L);
    values.put(10L, 4L);
    values.put(100L, 4L);
    values.put(1000L, 454L);
    values.put(10000L, 454L);
    values.put(100000L, 45454L);
    values.put(1000000L, 45454L);
    values.put(10000000L, 4545454L);
    values.put(100000000L, 4545454L);
    values.put(1000000000L, 454545454L);
    values.put(10000000000L, 454545454L);
    values.put(100000000000L, 45454545454L);
    values.put(1000000000000L, 45454545454L);
    values.put(10000000000000L, 4545454545454L);
    values.put(100000000000000L, 4545454545454L);
    values.put(1000000000000000L, 454545454545454L);
    values.put(10000000000000000L, 454545454545454L);
    values.put(100000000000000000L, 45454545454545454L);
    values.put(1000000000000000000L, 45454545454545454L);
}
 
// Function that returns the number of
// even and odd digits in val
static long[] count_even_odd(long val)
{
    long even = 0, odd = 0;
    while (val > 0)
    {
        long num = val % 10;
        if (num % 2 == 0)
            even++;
        else
            odd++;
             
        val /= 10;
    }
    return (new long[] { even, odd });
}
 
// Function that returns True if num
// satisfies the given condition
static boolean satisfies_condition(long num)
{
    long[] answer = count_even_odd(num);
    long even = answer[0];
    long odd = answer[1];
 
    if (even % 2 == 1 && odd % 2 == 0)
        return true;
         
    return false;
}
 
// Function to return the count of
// numbers from 1 to val that
// satisfies the given condition
static long count_upto(long val)
{
     
    // If the value is already present
    // in the values dict
    if (values.containsKey(val))
        return values.get(val);
 
    long index = 1;
    for(int i = 0;
            i < Long.toString(val).length() - 1;
            i++)
        index *= 10;
 
    // If the value is even
    // Case 2
    if (Long.toString(val).length() % 2 == 0)
        return values.get(index);
 
    long val_len = Long.toString(val).length();
    long cnt = values.get(index);
 
    // Now the problem is to count the desired
    // numbers from 10**(val_len-1) + 1 to val
    long left_end = index + 1;
 
    // Case 3
    // Eliminating all the even numbers
    cnt += (val - left_end) / 2;
    if (satisfies_condition(val) ||
        satisfies_condition(left_end))
        cnt++;
 
    return cnt;
}
 
// Driver Code
public static void main(String[] args)
{
     
    // Input l and r
    long l = 123, r = 984;
 
    // Function to initialize the Map
    intitializeMap();
 
    long right = count_upto(r);
    long left = 0;
 
    if (l == '1')
        left = 0;
    else
        left = count_upto(l - 1);
 
    System.out.println(right - left);
}
}
 
// This code is contributed by Kingash


Python3
# Python3 implementation of the approach
 
# Pattern table from Case 1
values = {
    1: 0,
    10: 4,
    100: 4,
    1000: 454,
    10000: 454,
    100000: 45454,
    1000000: 45454,
    10000000: 4545454,
    100000000: 4545454,
    1000000000: 454545454,
    10000000000: 454545454,
    100000000000: 45454545454,
    1000000000000: 45454545454,
    10000000000000: 4545454545454,
    100000000000000: 4545454545454,
    1000000000000000: 454545454545454,
    10000000000000000: 454545454545454,
    100000000000000000: 45454545454545454,
    1000000000000000000: 45454545454545454,
}
 
# Function that returns the number of
# even and odd digits in val
def count_even_odd(val):
    even = odd = 0
    while val > 0:
        num = val % 10
        if num % 2 == 0:
            even += 1
        else:
            odd += 1
        val //= 10
 
    return even, odd
 
# Function that returns True if num
# satisfies the given condition
def satisfies_condition(num):
    even, odd = count_even_odd(num)
    if even % 2 == 1 and odd % 2 == 0:
        return True
    return False
 
 
# Function to return the count of numbers
# from 1 to val that satisfies the given condition
def count_upto(val):
 
    # If the value is already present in the
    # values dict
    if int(val) in values:
        return values[int(val)]
 
    # If the value is even
    # Case 2
    if len(val) % 2 == 0:
        return values[int('1' + '0' * (len(val) - 1))]
 
    val_len = len(val)
    count = values[int('1' + '0' * (val_len - 1))]
 
    # Now the problem is to count the desired
    # numbers from 10**(val_len-1) + 1 to val
    left_end = int('1' + '0' * (val_len - 1)) + 1
 
    # Case 3
    # Eliminating all the even numbers
    count += (int(val) - left_end) // 2
 
    if satisfies_condition(int(val)) or satisfies_condition(left_end):
        count += 1
    return count
 
 
if __name__ == '__main__':
 
    # Input L and R ( as a string )
    l, r = '123', '984'
 
    right = count_upto(r)
 
    left = 0
    if(l == '1'):
        left = 0
    else:
        left = count_upto(str(int(l)-1))
 
    print(right - left)


输出:
431

时间复杂度: O(logn)