给定一个范围L和R,对L到R之间的所有数字进行计数,以使每个数字的位数之和和每个数字的平方之和为Prime 。
注意: 10 <= [L,R] <= 10 8
例子:
Input: L = 10, R = 20
Output: 4
Such types of numbers are: 11 12 14 16
Input: L = 100, R = 130
Output: 9
Such types of numbers are : 101 102 104 106 110 111 113 119 120
天真的方法:
只需获取每个数字的位数和每个数字的位数平方的和,然后检查它们是否均为质数即可。
高效方法:
- 在这种方法中,存在可以进行优化的观察结果:
- 现在,如果仔细查看范围,则该数字为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
笔记:
- 如果有多个查询要求找出介于L和R之间的数字,则有两种方法:
- 将满足上述条件的所有数字存储在另一个数组中,并使用二进制搜索来找出数组中小于R的元素个数(例如cnt1) ,以及数组小于L的元素个数个数(例如cnt2) 。返回cnt1 – cnt2
时间复杂度:每个查询O(log(N)) 。 - 我们可以使用前缀数组或DP方法,以便它已经存储了多少个。从索引0到i都是上述类型的好,并通过给定DP [R] – DP [L-1]返回总计数
时间复杂度:每个查询O(1) 。