📜  查找范围L到R之间的所有数字,以使数字和与数字的平方和为质数

📅  最后修改于: 2021-05-06 21:03:36             🧑  作者: Mango

给定一个范围LR,LR之间的所有数字进行计数,以使每个数字的位数之和每个数字的平方之和为Prime

注意: 10 <= [L,R] <= 10 8

例子:

天真的方法:
只需获取每个数字的位数和每个数字的位数平方的和,然后检查它们是否均为质数即可。

高效方法:

    在这种方法中,存在可以进行优化的观察结果:
  • 现在,如果仔细查看范围,则该数字为10 8,即小于该数字的最大数字将为99999999,并且可以形成的最大数字为8 *(9 * 9)= 648 (因为数字平方和为9 2 + 9 2 +…8倍),因此我们只需要648的底漆即可,这可以使用Eratosthenes的筛子完成。
  • 现在,对范围内的每个数字进行迭代,并检查其是否满足上述条件。

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
  
// Sieve of prime numbers
void primesieve(vector& prime)
{
    // Sieve to store whether a
    // number is prime or not in
    // O(nlog(log(n)))
    prime[1] = false;
  
    for (int p = 2; p * p <= 650; p++) {
        if (prime[p] == true) {
            for (int i = p * 2; i <= 650; i += p)
                prime[i] = false;
        }
    }
}
  
// Function to return sum of digit
// and sum of square of digit
pair sum_sqsum(int n)
{
  
    int sum = 0;
    int sqsum = 0;
    int x;
  
    // Until number is not
    // zero
    while (n) {
        x = n % 10;
        sum += x;
        sqsum += x * x;
        n /= 10;
    }
  
    return (make_pair(sum, sqsum));
}
  
// Function to return the count
// of number form L to R
// whose sum of digits and
// sum of square of digits
// are prime
int countnumber(int L, int R)
{
  
    vector prime(651, true);
  
    primesieve(prime);
  
    int cnt = 0;
  
    // Iterate for each value
    // in the range of L to R
    for (int i = L; i <= R; i++) {
  
        // digit.first stores sum of digits
        // digit.second stores sum of
        // square of digit
        pair digit = sum_sqsum(i);
  
        // If sum of digits and sum of
        // square of digit both are
        // prime then increment the count
        if (prime[digit.first]
            && prime[digit.second]) {
            cnt += 1;
        }
    }
  
    return cnt;
}
  
// Driver Code
int main()
{
  
    int L = 10;
    int R = 20;
  
    cout << countnumber(L, R);
}


Java
// Java implementation of the approach
import java.util.*;
  
class GFG 
{
static class pair
{ 
    int first, second; 
    public pair(int first, int second) 
    { 
        this.first = first; 
        this.second = second; 
    } 
}
  
// Sieve of prime numbers
static void primesieve(boolean []prime)
{
    // Sieve to store whether a
    // number is prime or not in
    // O(nlog(log(n)))
    prime[1] = false;
  
    for (int p = 2; p * p <= 650; p++)
    {
        if (prime[p] == true)
        {
            for (int i = p * 2; i <= 650; i += p)
                prime[i] = false;
        }
    }
}
  
// Function to return sum of digit
// and sum of square of digit
static pair sum_sqsum(int n)
{
    int sum = 0;
    int sqsum = 0;
    int x;
  
    // Until number is not
    // zero
    while (n > 0)
    {
        x = n % 10;
        sum += x;
        sqsum += x * x;
        n /= 10;
    }
    return (new pair(sum, sqsum));
}
  
// Function to return the count
// of number form L to R
// whose sum of digits and
// sum of square of digits
// are prime
static int countnumber(int L, int R)
{
    boolean []prime = new boolean[651];
  
    Arrays.fill(prime, true);
    primesieve(prime);
  
    int cnt = 0;
  
    // Iterate for each value
    // in the range of L to R
    for (int i = L; i <= R; i++) 
    {
  
        // digit.first stores sum of digits
        // digit.second stores sum of
        // square of digit
        pair digit = sum_sqsum(i);
  
        // If sum of digits and sum of
        // square of digit both are
        // prime then increment the count
        if (prime[digit.first] && 
            prime[digit.second]) 
        {
            cnt += 1;
        }
    }
    return cnt;
}
  
// Driver Code
public static void main(String[] args) 
{
    int L = 10;
    int R = 20;
  
    System.out.println(countnumber(L, R));
}
} 
  
// This code is contributed by PrinciRaj1992


Python3
# Python3 implementation of the approach 
from math import sqrt
  
# Sieve of prime numbers 
def primesieve(prime) :
  
    # Sieve to store whether a 
    # number is prime or not in 
    # O(nlog(log(n))) 
    prime[1] = False; 
  
    for p in range(2, int(sqrt(650)) + 1) :
        if (prime[p] == True) :
            for i in range(p * 2, 651, p) : 
                prime[i] = False; 
  
# Function to return sum of digit 
# and sum of square of digit 
def sum_sqsum(n) :
  
    sum = 0; 
    sqsum = 0; 
  
    # Until number is not 
    # zero 
    while (n) :
        x = n % 10; 
        sum += x; 
        sqsum += x * x; 
        n //= 10; 
  
    return (sum, sqsum); 
  
# Function to return the count 
# of number form L to R 
# whose sum of digits and 
# sum of square of digits 
# are prime 
def countnumber(L, R): 
  
    prime = [True] * 651; 
  
    primesieve(prime); 
  
    cnt = 0; 
  
    # Iterate for each value 
    # in the range of L to R 
    for i in range(L, R + 1) :
          
        # digit.first stores sum of digits 
        # digit.second stores sum of 
        # square of digit 
        digit = sum_sqsum(i); 
  
        # If sum of digits and sum of 
        # square of digit both are 
        # prime then increment the count 
        if (prime[digit[0]] and prime[digit[1]]) :
            cnt += 1; 
  
    return cnt; 
  
# Driver Code 
if __name__ == "__main__" : 
  
    L = 10; 
    R = 20; 
  
    print(countnumber(L, R)); 
  
# This code is contributed by AnkitRai01


C#
// C# implementation of the approach
using System;
      
class GFG 
{
public class pair
{ 
    public int first, second; 
    public pair(int first, int second) 
    { 
        this.first = first; 
        this.second = second; 
    } 
}
  
// Sieve of prime numbers
static void primesieve(bool []prime)
{
    // Sieve to store whether a
    // number is prime or not in
    // O(nlog(log(n)))
    prime[1] = false;
  
    for (int p = 2; p * p <= 650; p++)
    {
        if (prime[p] == true)
        {
            for (int i = p * 2;
                     i <= 650; i += p)
                prime[i] = false;
        }
    }
}
  
// Function to return sum of digit
// and sum of square of digit
static pair sum_sqsum(int n)
{
    int sum = 0;
    int sqsum = 0;
    int x;
  
    // Until number is not
    // zero
    while (n > 0)
    {
        x = n % 10;
        sum += x;
        sqsum += x * x;
        n /= 10;
    }
    return (new pair(sum, sqsum));
}
  
// Function to return the count
// of number form L to R
// whose sum of digits and
// sum of square of digits
// are prime
static int countnumber(int L, int R)
{
    bool []prime = new bool[651];
    for (int i = 0; i < 651; i++) 
        prime[i] = true;
    primesieve(prime);
  
    int cnt = 0;
  
    // Iterate for each value
    // in the range of L to R
    for (int i = L; i <= R; i++) 
    {
  
        // digit.first stores sum of digits
        // digit.second stores sum of
        // square of digit
        pair digit = sum_sqsum(i);
  
        // If sum of digits and sum of
        // square of digit both are
        // prime then increment the count
        if (prime[digit.first] && 
            prime[digit.second]) 
        {
            cnt += 1;
        }
    }
    return cnt;
}
  
// Driver Code
public static void Main(String[] args) 
{
    int L = 10;
    int R = 20;
  
    Console.WriteLine(countnumber(L, R));
}
}
  
// This code is contributed by 29AjayKumar


输出:
4

笔记:

    如果有多个查询要求找出介于LR之间的数字,则有两种方法:
  1. 将满足上述条件的所有数字存储在另一个数组中,并使用二进制搜索来找出数组中小于R的元素个数(例如cnt1) ,以及数组小于L的元素个数个数(例如cnt2) 。返回cnt1 – cnt2
    时间复杂度:每个查询O(log(N))
  2. 我们可以使用前缀数组或DP方法,以便它已经存储了多少个。从索引0到i都是上述类型的好,并通过给定DP [R] – DP [L-1]返回总计数
    时间复杂度:每个查询O(1)