Find maximum occurrence digit in a range of prime numbers - arrays

Given two number a and b (1 <= a <= b <= 10^6). Find most frequent digit among all prime numbers between a and b inclusive. if frequency is same print highest digit.
Example: from 1 to 20, prime numbers are - 2, 3, 5, 7, 11, 13, 17, 19. Here 2, 5, 9 occur only once, 3, 7 occur twice, and 1 occurs 5 times. So the result is 1.
One basic approach is:
In the range [a, b] - find all prime numbers.
Take one count array to count occurrences from 0 to 9.
For all the prime numbers in the range, extract all the digits and increment the count for the digits accordingly in the count array.
Find out max from the count array.
But this is inefficient for a large range say [1, 1000000].
Is there any efficient method to accomplish this?

Do a sieve of Eratosthenes to find all the prime numbers in the range 0, 106. This can be done quite fast(in under 1 sec on a modest machine). Use 10 auxiliary arrays - one for each of the digits each of the arrays with size 106. If a number is not prime have 0 stored all 10 arrays. If a number is prime, store in each array the number of times the given digit appears in the number. After that cycle over each of the arrays and accumulate prefix sums of the number of occurrences of the given digit. This can be done quite easily in linear time. Say for digit 3:
for (int i = 1; i < n; ++i) {
a3[i] += a3[i-1];
}
Having those arrays you can count the number of occurrences of each digit in a specified interval in constant time. Namely the number of occurrences of 3 in the interval [x,y] is a3[y] - a3[x-1](take care of special case when x is 0).
The computational complexity of this algorithm is the same as the one of sieve of Eratosthenes for the precomputation and constant for each query. The memory complexity is linear. You can improve the memory overhead by only storing values for the prime numbers in the auxiliary arrays, thus having them with size equal of the number of prime numbers up to 106 if need be. However this would make the implementation slightly trickier.

function writeOutput(left, right) {
let digitCount = new Array(10);
digitCount.fill(0)
for(let num = left ; num <= right; num++){
if(isPrime(num)){
let copyNum = num;
while (copyNum > 0){
let d = copyNum % 10;
digitCount[d]++;
copyNum = copyNum / 10;
}
}
}
let maxCount = 0;
let maxNum = 0;
for (let j = 0; j < digitCount.length; j++){
if(digitCount[j] > maxCount){
maxCount = digitCount[j];
maxNum = j;
}
}
if(maxCount == 1){
for(let k = digitCount.length - 1; k > 0; k--){
if(digitCount[k] > 0){
maxNum = k;
break;
}
}
} else if( maxCount > 1){
return maxNum;
} else {
maxNum = -1;
}
return maxNum
}
function isPrime(n){
for(let i = 2; i * i <= n; i++){
if(n % i == 0){
return false
}
}
return true
}

Related

Calculate the maximal even cost subarray

I am new to Algorithms and Competitive Programming. I am learning about Dynamic programming and I have a problem as below:
Given an array with n numbers. Define a sub-array is a[i, j] = {a[i], a[i + 1], ..., a[j]}, in other words, elements must be contiguous.
The problem is the find the maximum weight of a sub-array such that
that weight is an even number.
The input is 2 <= n <= 1000000; -100 <= a[i] <= 100
Sample test:
5
-2 1 -4 4 9
Output: 10
For this problem, I can do brute force but with a large value of n, I can not do it with the time limit is 1 second. Therefore, I want to change it to Dynamic programming.
I have an idea but I do not know if it works. I think I can divide this problem into two sub-problems. For each element/number, I consider if it is odd/even and then find the largest sum with its corresponding property (odd + odd or even + even to get a even sum). However, that is just what I think and I really need your help.
Here is C++ algorithm with O(n) time complexity:
const int Inf = 1e9;
int main() {
int n = 5;
vector<int> inputArray = {-2, 1, -4, 4, 9};
int minEvenPrefixSum = 0, minOddPrefixSum = Inf;
bool isOddPrefixSumFound = false;
int prefixSum = 0, answer = -Inf;
for(int i = 0; i < n; ++i) {
prefixSum += inputArray[i];
if(abs(prefixSum) % 2 == 0) {
answer = max(answer, prefixSum - minEvenPrefixSum);
minEvenPrefixSum = min(minEvenPrefixSum, prefixSum);
} else {
if(isOddPrefixSumFound) {
answer = max(answer, prefixSum - minOddPrefixSum);
}
isOddPrefixSumFound = true;
minOddPrefixSum = min(minOddPrefixSum, prefixSum);
}
}
if(answer == -Inf) {
cout << "There is no subarray with even sum";
} else {
cout << answer;
}
}
Explanation:
As #nico-schertler mentioned in commentary this task is very similar with more basic problem of the maximum-sum contiguous sub array. How to solve basic task with O(n) time complexity you can read here.
Now let's store not just one value of the minimum prefix sum, but two. One is for minimum even prefix sum, and the other is for minimum odd prefix sum. As a result, when we process the next number, we look at what the value of the prefix sum becomes. If it is even, we try to update the answer using the minimum even value of the prefix sum, in the other case using the minimum odd value of the prefix sum.

C program that outputs if a number is divisble by 3 or not

I am new to programming, and I have to make an assignment in C. I have to make a program that reads an integer n and outputs if it is divisible by 3. Unfortunately I am not allowed to use the % operator to check this. "A positive integer is divisible by 3 if and only if the sum of all its digits is divisible by 3." So the program must add the digits of n, and if this is larger then 9, I have to add the digits of this number etc, until the sum of the digits is equal to or less then 9. Because then I am allowed to say whether n is divisible by 3 or not. I also have to print the number of the lose digits each time. For example: input:9999-----output:9999 -> 36 -> 9. YES.
I made a loop:
while(n>9){
lastDigit = n%10;
sumDigits += lastDigit;
n = (n-lastDigit)/10;
}
sumDigits = sumDigits + n; /*this is the sum of the digits*/
Now if this is larger then 9, I have to enter this number in the loop again, but I don't know how to do this. I made 3 other loops with if else statements, but that way my program is way to long. How can I make my program shorter? Because some numbers have to go through the loop multiple times.
Thanks.
Niek
You need two loops here - one that will loop as long as n > 9 and another to loop over the digits of n and sum them:
int origN = n;
while (n > 9) {
int sum = 0;
int tmp = n;
while (tmp > 0) {
int lastDigit = n % 10;
sum += lastDigit;
tmp /= 10;
}
n = sum;
}
if (n == 3 || n == 6 || n == 9) {
printf("%d is divisible by 3\n", origN);
} else {
printf("%d is not divisible by 3\n", origN);
}

Given an array of numbers, find a number to start with such that the sum is never negative

Given an array of integers, find the smallest number X to start with, such that adding elements of array to X, the sum is always greater than 0
If given array is {-2, 3, 1, -5}
For example, in the above array, X should be 4
Explanation:
If, we start with 4, then adding first number -2, array sum becomes 4 + (-2) = 2 (which is >0)
Now adding next element 3 to current sum which is 2, 2+ 3 = 5 (which is >0)
Adding next element 1 to new sum 5 gives, 5 + 1 = 6 (which is >0)
Adding last element -5 to new sum 6 gives 6 + (-5) = 1, which is again greater than zero.
Given an array of integers, How can I find the smallest number X?
Find minimum of cumulative sum for given array.
Needed result is 1 - MinC
A = [-2, 3, 1, -5]
CSum = 0
MinC = 10000000000
for x in A:
CSum += x
MinC = min(MinC, CSum)
Addend = 1 - MinC
print(Addend)
>>> 4
First we should check if element at ith position is greater than zero or not. If element is greater than zero then no problem and we can add it directly to our sum, ans remains unchanged. But if not greater than zero then we first check whether sum is greater than element or not. If sum is greater than abs(arr[I]) then then we decrease our sum by abs(arr[I]), ans remains unchanged but if abs(arr[I]) is greater than sum then we add abs(arr[i]-sum+1) to ans and initialise sum to 1.
Below is code for same:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
// considering x>=0(x can't take values less than 0)
ll arr[] = { -2, 3, 1, -5};
ll n = sizeof(arr) / sizeof(ll);
ll ans = 0; // My answer
ll sum = 0; // current sum of elements
for (ll i = 0; i < n; i++)
{
if (arr[i] <= 0)
{
if ((sum + arr[i]) <= 0)
{
ans += (abs(sum + arr[i]) + 1); //add 1 to make sum=1
sum = 1;
}
else
sum += arr[i]; // added because arr[i]<=0,(sum-=abs(arr[i]))
}
else
sum += arr[i];
}
cout << ans;
return 0;
}
// ans=4 for this case
you should find miniminum subarray sum first. lets say it comes equal to k.
your answer should be k+1. you can find minimum sum here :
https://www.geeksforgeeks.org/smallest-sum-contiguous-subarray/
This problem can be solved with the simple logic by precomputing the sum of all the elements present in the array.
Find the Sum of all the elements present in the array.
If sum equals zero return 1 as it will give smallest number on adding which we will get the total sum greater than zero.
If sum greater than zero return a negative number just less than that sum ( handle the special case of sum == 1 seperately)
If sum is negative then return the positive number just one greater than the sum in magnitude.
Step 1 : Find the Sum of all the Elements in the array
int sum = 0;
for(int i = 0; i < arr.size(); i++)
{
sum += arr[i];
}
Step 2 : Check The Sum obtained and Apply the following logic
if(sum == 0)
return 1;
else if( sum < 0)
return abs(sum)+1;
else
{
if( sum == 1)
return 0;
else
return -(sum-1);
}

finding number of numbers which have prime number of factors

The problem is to find the number of divisors of a number
ex-
for 10
ans=4
since 1,2,5,10 are the numbers which are divisors
i.e. they are the factors
constraints are num<=10^6
I have implemented a code for the same but got TLE!!
here is my code
int isprime[MAX];
void seive()
{
int i,
j;
isprime[0] = isprime[1] = 1;
for (i = 4; i < MAX; i += 2)
isprime[i] = 1;
for (i = 3; i * i < MAX; i += 2) {
if (!isprime[i]) {
for (j = i * i; j < MAX; j += 2 * i)
isprime[j] = 1;
}
}
}
int main()
{
seive();
int t;
long long num;
scanf("%d", & t);
while (t--) {
scanf("%lld", & num);
cnt = 0;
for (j = 1; j * j <= num; j++) {
if (num % j == 0) {
cnt++;
if (num / j != j)
cnt++;
}
printf("%lld\n", cnt);
}
return 0;
}
Can somebody help me to optimize it?
I have also searched about it but didnot getting any sucess.
So Please help guys.
You could try computing this mathematically (I'm not sure this will be faster/easier). Basically, given the prime factorization of a number, you should be able to calculate the number of divisors without too much trouble.
If you have an input x decompose into something like
x = p1^a1 * p2^a2 * ... pn^an
Then the number of divisors should be
prod(ai + 1) for i in 1 to n
I would then look at finding the smallest prime < sqrt(x), dividing that out until you're left with just a prime. A sieve might still be useful and I don't know what kind of input you would be getting.
Now consider what the above statement says: the number of divisors in the product of the powers of the prime factorization (plus 1). Thus, if you only every care if the result is prime, then you should only ever consider numbers which are prime, or powers of primes. And within that, you then only need to consider powers such that a1 + 1 is prime.
That should significantly cut down your search space.
If the prime factorization of a number is:
x = p1^e1 * p2^e2 * ... * pk^ek
Then the number of divisors is:
(e1 + 1)*(e2 + 1)* ... *(ek + 1)
For this to be prime, you need all ei to be 0, except one, which needs to be a prime - 1.
This is only true for primes and powers of primes. So you need to find how many powers of primes are in [l, r]. For example, 2^6 has (6 + 1) = 7 prime factors.
Now you just need to sieve enough primes fast enough. You only need to sieve those in [l, r], so an interval of size max 10^6.
To sieve directly in this interval, remove multiples of 2 directly from [l, r], and same for the rest. You can sieve primes up to 10^6 and use those to do the interval sieving later.
You can do the necessary counting while you're sieving as well.

Finding prime factors in C

I am trying to generate all the prime factors of a number n. When I give it the number 126 it gives me 2, 3 and 7 but when I give it say 8 it gives me 2, 4 and 8. Any ideas as to what I am doing wrong?
int findPrime(unsigned long n)
{
int testDivisor, i;
i = 0;
testDivisor = 2;
while (testDivisor < n + 1)
{
if ((testDivisor * testDivisor) > n)
{
//If the test divisor squared is greater than the current n, then
//the current n is either 1 or prime. Save it if prime and return
}
if (((n % testDivisor) == 0))
{
prime[i] = testDivisor;
if (DEBUG == 1) printf("prime[%d] = %d\n", i, prime[i]);
i++;
n = n / testDivisor;
}
testDivisor++;
}
return i;
}
You are incrementing testDivisor even when you were able to divide n by it. Only increase it when it is not divisible anymore. This will result in 2,2,2, so you have to modify it a bit further so you do not store duplicates, but since this is a homework assignment I think you should figure that one out yourself :)
Is this based on an algorithm your professor told you to implement or is it your own heuristic? In case it helps, some known algorithms for prime factorization are the Quadratic Sieve and the General Number Field Sieve.
Right now, you aren't checking if any divisors you find are prime. As long as n % testDivisor == 0 you are counting testDivisor as a prime factor. Also, you are only dividing through by testDivisor once. You could fix this a number of ways, one of which would be to replace the statement if (((n % testDivisor) == 0)) with while (((n % testDivisor) == 0)).
Fixing this by adding the while loop also ensures that you won't get composite numbers as divisors, as if they still divide n, a smaller prime factor must have also divided n and the while loop for that prime factor wouldn't have left early.
Here is code to find the Prime Factor:
long GetPrimeFactors(long num, long *arrResult)
{
long count = 0;
long arr[MAX_SIZE];
long i = 0;
long idx = 0;
for(i = 2; i <= num; i++)
{
if(IsPrimeNumber(i) == true)
arr[count++] = i;
}
while(1)
{
if(IsPrimeNumber(num) == true)
{
arrResult[idx++] = num;
break;
}
for(i = count - 1; i >= 0; i--)
{
if( (num % arr[i]) == 0)
{
arrResult[idx++] = arr[i];
num = num / arr[i];
break;
}
}
}
return idx;
}
Reference: http://www.softwareandfinance.com/Turbo_C/Prime_Factor.html
You can use the quadratic sieve algorithm, which factors 170-bit integers in second and 220-bit integers in minute. There is a pure C implementation here that does not require GMP or an external library : https://github.com/michel-leonard/C-Quadratic-Sieve, it's able to provide you a list of the prime factors of N. Thank You.

Resources