Modulur arithmetic logic to reduce calculations - java

the concept of mod to retain only the remainder instead of the big number.
formula to compute:
=> Summation i=1 to i=N { i%m }
Constraint
1 ≤ N ≤ 10^9
1 ≤ m ≤ 10^9
How can modulus used so that we need not to sum up to 10^9 (big Number).
Java code gives terminated due to timeout or CPU code duped Error on big number execution.
CODE: k is the summation result to be printed.
for (BigInteger bi = BigInteger.valueOf(1);
bi.compareTo(N) <= 0;
bi = bi.add(BigInteger.ONE)){
k = k.add(bi.mod(m));
}
System.out.println(k);

I think I understand what you're asking in which case it's really more of an arithmetic than a programming question but here it is anyway.
Try a concrete example. If you have the sum with i from 1 to 10 of i % 3, what you are adding its 1 + 2 + 0 + 1 + 2 + 0 + 1 + 2 + 0 + 1. You can see that you have the same thing over and over so what you need to do is figure out what that is, figure out how many times you need to add it, then add on the leftover bit on the end.

Related

Improve performance of string to binary number conversion

This is one of the questions that I faced in competitive programming.
Ques) You have an input String which is in binary format 11100 and you need to count number of steps in which number will be zero. If number is odd -> subtract it by 1, if even -> divide it by 2.
For example
28 -> 28/2
14 -> 14/2
7 -> 7-1
6 -> 6/2
3 -> 3-1
2 -> 2/2
1-> 1-1
0 -> STOP
Number of steps =7
I came up with the following solutions
public int solution(String S) {
// write your code in Java SE 8
String parsableString = cleanString(S);
int integer = Integer.parseInt(S, 2);
return stepCounter(integer);
}
private static String cleanString(String S){
int i = 0;
while (i < S.length() && S.charAt(i) == '0')
i++;
StringBuffer sb = new StringBuffer(S);
sb.replace(0,i,"");
return sb.toString();
}
private static int stepCounter(int integer) {
int counter = 0;
while (integer > 0) {
if (integer == 0)
break;
else {
counter++;
if (integer % 2 == 0)
integer = integer / 2;
else
integer--;
}
}
return counter;
}
The solution to this question looks quite simple and straightforward, however the performance evaluation of this code got me a big ZERO. My initial impressions were that converting the string to int was a bottleneck but failed to find a better solution for this. Can anybody please point out to me the bottlenecks of this code and where it can be significantly improved ?
If a binary number is odd, the last (least significant) digit must be 1, so subtracting 1 is just changing the last digit from 1 to 0 (which, importantly, makes the number even).
If a binary number is even, the last digit must be 0, and dividing by zero can be accomplished by simply removing that last 0 entirely. (Just like in base ten, the number 10 can be divided by ten by taking away the last 0, leaving 1.)
So the number of steps is two steps for every 1 digit, and one step for every 0 digit -- minus 1, because when you get to the last 0, you don't divide by 2 any more, you just stop.
Here's a simple JavaScript (instead of Java) solution:
let n = '11100';
n.length + n.replace(/0/g, '').length - 1;
With just a little more work, this can deal with leading zeros '0011100' properly too, if that were needed.
Number of times you need to subtract is the number of one bits which is Integer.bitCount(). Number of times you need to divide is the position of most-significant bit which is Integer.SIZE (32, total number of bits in integer) minus Integer.numberOfLeadingZeros() minus one (you don't need to divide 1). For zero input I assume, the result should be zero. So we have
int numberOfOperations = integer == 0 ? 0 : Integer.bitCount(integer) +
Integer.SIZE - Integer.numberOfLeadingZeros(integer) - 1;
As per the given condition, we are dividing the number by 2 if it is even which is equivalent to remove the LSB, again if number is odd we are subtracting 1 and making it an even which is equivalent to unset the set bit (changing 1 to 0). Analyzing the above process we can say that the total number of steps required will be the sum of (number of bits i.e. (log2(n) +1)) and number of set bits - 1(last 0 need not to be removed).
C++ code:
result = __builtin_popcount(n) + log2(n) + 1 - 1;
result = __builtin_popcount(n) + log2(n);

Count number of pairs of two numbers less than or equal to N such that Sum of the digits of numbers of pair is Prime

Given a number N, count all pairs (X,Y) such that sum of to the digits of X and Y is prime. Conditions are as follows.
1 <= N <= 10^50
0 <= X,Y <= N
(X,Y) and (Y,X) are same pair.
I could think of brute force approach. In which I need to put two loops ranging from 1 to N and compute sum of digits for each x and y pair and check whether its prime or not. But its not an optimal solution as N has range 10^50.
I've been taking a stab at this -- it took me a couple of tries just to understand the problem. I want to write up what I learned before I give up and move onto something easier!
First, my rework of #shiva's solution that produces correct output faster:
import sys
from functools import lru_cache
def sum_of_digits(number):
summation = 0
while number > 0:
summation += number % 10
number //= 10
return summation
#lru_cache()
def is_prime(number):
if number < 2:
return False
if number % 2 == 0:
return number == 2
divisor = 3
while divisor * divisor <= number:
if number % divisor == 0:
return False
divisor += 2
return True
maximum = int(sys.argv[1])
count = 0
for i in range(maximum + 1):
sum_i = sum_of_digits(i)
for j in range(i, maximum + 1):
if is_prime(sum_i + sum_of_digits(j)):
count += 1
print(count)
I use this as a benchmark below for both speed and accuracy.
The number of primes needed is trivial, even for 10^50, and can/should be computed ahead. The number of digit sums that are generated is also relatively small and can be stored/hashed. My solution hashes all the possible digit sums from 0 to 10^N, storing the number of times each sum is generated as the value. It then does a pair of nested loops over the digit sums (keys) and if the sum of those sums is a prime, it adds to the count the product of the number of ways each sum can be computed (i.e. multiplies the values).
import sys
from math import ceil
from collections import defaultdict
VERBOSE = False
def sum_of_digits(number):
summation = 0
while number:
summation += number % 10
number //= 10
return summation
def sieve_primes(n):
sieve = [False, False] + [True] * (n - 1)
divisor = 2
while divisor * divisor <= n:
if sieve[divisor]:
for i in range(divisor * divisor, n + 1, divisor):
sieve[i] = False
divisor += 1
return [number for number in range(2, n + 1) if sieve[number]]
power = int(sys.argv[1]) # testing up to 10 ** power
maximum_sum_of_digits = 18 * power
primes_subset = sieve_primes(maximum_sum_of_digits)
sums_of_digits = defaultdict(int)
for i in range(10 ** power + 1):
sums_of_digits[sum_of_digits(i)] += 1
if VERBOSE:
print('maximum sum of digits:', maximum_sum_of_digits)
print('maximum prime:', primes_subset[-1])
print('number of primes:', len(primes_subset))
print('digit sums cached', len(sums_of_digits))
primes_subset = set(primes_subset)
count = 0
for i in sums_of_digits:
sum_i = sums_of_digits[i]
for j in sums_of_digits:
if i + j in primes_subset:
count += sum_i * sums_of_digits[j]
print(ceil((count + 2) / 2)) # hack to help adjust between duples and no duples count; sigh
(Turn on the VERBOSE flag to see more information about the problem.)
Unfortunately, this counts both (X, Y) and (Y, X), contrary to the problem specification, so there's an approximate correction hack at the end of the code to adjust for this. (Please suggest an exact correction!) I call my result an approximation but it usually only undercounts by 1 or 2. Unlike #shiva's code, this one takes a power of 10 as its argument since it's goal is to see how close to 10^50 it can get.
Would be glad to see a result for N=10^50 (or at least 10^8) – MBo
#Shiva reworked My Attempt
exact secs approx secs
10^1 24 0.03 24 0.03
10^2 1544 0.04 1544 0.04
10^3 125030 0.49 125029 0.04
10^4 12396120 51.98 12396119 0.05
10^5 1186605815 6223.28 1186605813 0.14
10^6 113305753201 1.15
10^7 11465095351914 12.36
10^8 1120740901676507 137.37
10^9 105887235290733264 1626.87
#shiva's revamped solution is useless above 10^4 and mine bogs down above 10^8. So getting to 10^50 is going to take a different approach. I hope some of this code and analysis will help towards that effort.
Try this python code and debug:
def sumofdigits(num):
sum=0
while num>0:
sum+=num%10
num=num//10
return sum
def isprime(num):
if num==0:
return False
i = 2
while i<num:
if num%i==0:
return False
i+=1
return True
number = int(input("Enter number:"))
for i in range(0,number+1):
for j in range(i,number+1):
if isprime(sumofdigits(i)+sumofdigits(j)):
print(i,j);
Sample output:

Trying to find the number of x's that satisfies n + x = n ^ x fails with timeout

I'm trying to solve the following problem from the section Bit Manipulation at the Hacker Rank site using new features of Java 8 such as Streams.
The problem description:
Given an integer, n, find each x such that:
0 <= x <= n
n + x = n ^ x
where ^ denotes the bitwise XOR operator. Then print an integer denoting the total number of x's satisfying the criteria above.
Constraints
0 <= n <= 1015
Sample Input: 5
Sample Output: 2
Explanation:
For n = 5, the x values 0 and 2 satisfy the conditions:
5 + 0 = 5 ^ 0 = 5
5 + 2 = 5 ^ 2 = 7
Thus, we print 2 as our answer.
Sample Input: 10
Sample Output: 4
Explanation:
For n = 10, the x values 0, 1, 4, and 5 satisfy the conditions:
10 + 0 = 10 ^ 0 = 10
10 + 1 = 10 ^ 1 = 11
10 + 4 = 10 ^ 4 = 14
10 + 5 = 10 ^ 5 = 15
Thus, we print 4 as our answer.
My code is as follows:
public class SumVsXor
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
long n = in.nextLong();
long count = LongStream.rangeClosed(0, n)
.filter(k -> k + n == (k ^ n))
.count();
System.out.println(count);
}
}
The problem is this code doesn't pass all the test cases.
It works for small values of n, but for large values such as 1000000000000000 it fails due to timeout.
I wonder whether LongStream can't handle Streams with that many elements.
The problem with your code is that it is very inefficient. For the case of n==1000000000000000, your Stream pipeline is performing 1,000,000,000,000,000 addition and XOR operations, which takes a long time. Testing for each number between 0 and n whether n + x == n ^ x would take a long time even if you use a for loop instead of Streams.
Instead of checking all the numbers between 0 and n, you should try to figure out a better way to calculate the required total number of x's. That fact that this problem appears under a "Bit Manipulation" section should give you a hint
to look into the bits of numbers that satisfy n + x == n ^ x.
Let's consider the case of n==1000000000000000. The binary representation of that large number is
0000000000000011100011010111111010100100110001101000000000000000
=== == = ====== = = = == == =
--- - - - - -- -- --- - ---------------
~~~~~~~~~~~~~~
In order for n + x to be equal to n ^ x, x must have a 0 value in all the bits corresponding with the 1 bits of n (marked with = above), and either 0 or 1 value in the bits corresponding with the 0 bits of n (marked with - above). This doesn't include the leading 0s (marked with ~ above), since x must be <= n, so any leading 0s in n must also have a 0 value in x.
This means that the total number of x's for which n + x == n ^ x is 2the number of 0s in n, not including leading 0s.
In the case of n = 1000000000000000, there are 30 such 0 bits, so the total number of x's that satisfy the requirement is 230.
Here's one way to compute the total number of x's :
long n = 1000000000000000L;
int zeroBitsCount = 0;
while (n > 0) {
if (n % 2 == 0) {
zeroBitsCount++; // counts the number of non-leading 0 bits
}
n = n >> 1; // divide n by 2 in order to examine the next bit in the next iteration
}
long total = 1L << zeroBitsCount; // the total is 2^(the 0 bits count)
I came to the same result, but via a different explanation, so thought I might post it here.
Eran's answer got to the same conclusion that I did : to modify the zeroes in the binary representation of the initial number - that is pretty straightforward.
Let's suppose our number is
101010100
so it has 5 zeroes.
you need all the possible combinations of:
a single zero
two zeroes
three zeroes
four zeroes
five zeroes
that is actually :
comb(1,5) + comb(2,5) + comb(3,5) + comb(4,5) + comb (5,5)
that is a well known formula being equal to:
pow(2,n) // where n is five in our case
from there the solution is obvious...
This is a simple question if you know little bit about XOR. I don't know much about java. But I can explain in python.
1.First convert the number to binary.
2.Count the number of zeros in that binary number.
3.print 2 ^ (number of zeros) and that's it.
Here is my python code.
n = int(input())
sum = 0
if n!=0:
n=str(bin(n))
for i in range(len(n)):
if n[i]=='0':
sum = sum + 1
print(2**(sum-1))
else: print(1)
The reason to decrement the sum by 1 is, in python it convert the number to the binary as this format. e.g: 0b'10101.
public static void main (String[] args) {
Scanner in = new Scanner (System.in);
long n = in.nextLong();
long count = 1L << (64-Long.bitCount(n)-Long.numberOfLeadingZeros(n));
System.out.println(count);
}

Adding all numbers from 1 to N which have number of set bits as 2

I have a question where I have to add numbers from 1 to N which have their set bits as 2. Like for N = 5 we should get value 8, as number 3 and 5 have 2 bits set to one. I am implementing the same in java. I am getting the o/p correct for int value but when it comes to the long values, either it's taking a lot of time or freezing, and when I submit the same on code judge sites, it's giving run time exceeded message. Please guide me how may I optimise my code to run it faster, thanks :)
public static void main(String[] args)
{
long n = 1000000L;
long sum = 0;
long start = System.currentTimeMillis();
for(long i = 1L ; i <= n ; i++)
{
if(Long.bitCount(i) == 2)
{
sum += i;
}
}
long end = System.currentTimeMillis();
System.out.println(sum);
System.out.println("time="+(end-start));
}
As #hbejgel notes, there is no point in looping over all numbers and checking their bit count. You can simply construct numbers with 2 bits and add them up.
You can construct a number with 2 bits by picking two different bit positions in the long, the "higher" bit and the "lower" bit":
long i = (1 << higher) + (1 << lower);
So, you can simply loop over all such numbers, until the value you have constructed exceeds your limit:
long sum = 0;
outer: for (int higher = 1; higher < 63; ++higher) {
for (int lower = 0; lower < higher; ++lower) {
long i = (1 << higher) + (1 << lower);
if (i <= n) {
sum += i;
}
if (i >= n) break outer;
}
}
Let's say we know the closest number, x, equal to or lower than N with 2 set bits, then we can use the formula for power series to quickly sum all positions of the two set bits, for example, if x = b11000, we sum
4*2^0 + S(4)
+ 3*2^1 + S(4) - S(1)
+ 2*2^2 + S(4) - S(2)
+ x
where S(n) = 2 * (1 - 2^n) / (1 - 2) 
= 2 + 2^2 + 2^3 ... + 2^n
With numbers encoded 2 out of 5, exactly two bits are set in every one-digit number. The sum is 45, with the exception of N×(N-1)/2 for 0≤N<9.
I think the question is supposed to discover the pattern.
Fast forward. Given a number N, you can tell the largest number
should count by bitmask from the first two bits are set. So you have
a smaller number M
Skip to next counted number Given any number with two bit set, next
largest number is the shift the second bit by one, until underflow.
Skip to next order When underflow happens on set two, shift the
highest bit by one and also the bit on it's right.
You don't really need a loop on N, but the bits it have.
Next question: can you answer a large number? which N >100,000,000
Next Next question: can you answer the same question for X bits when X>2

Linear Recurrence for very large n

I was trying to solve this problem on SPOJ (http://www.spoj.pl/problems/REC/)
F(n) = a*F(n-1) + b where we have to find F(n) Mod (m)
where
0 <= a, b, n <= 10^100
1 <= M <= 100000
F(0)=1
I am trying to solve it with BigInteger in JAVA but if I run a loop from 0 to n its getting TLE. How could I solve this problem? Can anyone give some hint? Don't post the solution. I want hint on how to solve it efficiently.
Note that the pattern of residues mod (m) should have a repeating pattern in a linear recurrence, and with length <= m by the pigeonhole principle. You need only calculate the first m entries, then figure out which of those entries will apply to F(n) for the actual value of n.
It also helps to solve a simpler problem. Let's pick really small values, say a=2, b=1, m=5, n=1000.
F(0) = 1
F(1) = 2*F(0) + 1 = 2*1 + 1 = 3 -> 3 Mod 5 = 3
F(2) = 2*F(1) + 1 = 2*3 + 1 = 7 -> 7 Mod 5 = 2
F(3) = 2*F(2) + 1 = 2*7 + 1 = 15 -> 15 Mod 5 = 0
F(4) = 2*F(3) + 1 = 2*15 + 1 = 31 -> 31 Mod 5 = 1
F(5) = 2*F(4) + 1 = 2*31 + 1 = 63 -> 63 Mod 5 = 3
etc.
Notice that the residues are [1, 3, 2, 0, 1, 3, ...], which will repeat forever. So from this example, how would you determine F(1000) Mod 5 without looping all the way to the 1000th entry?
First, I'll tell you how to solve a simpler problem. Suppose that b is zero. Then you just need to calculate an mod M. Instead of multiplying n-1 times, use a divide-and-conquer technique:
// Requires n >= 0 and M > 0.
int modularPower(int a, int n, int M) {
if (n == 0)
return 1;
int result = modularPower(a, n / 2, M);
result = (result * result) % M;
if (n % 2 != 0)
result = (result * a) % M;
return result;
}
So you can calculate an in terms of afloor(n/2), then square that, and multiply by a again if n is odd.
To solve your problem, first define the function f(x) = (a x + b) (mod M). You need to calculate fn(1), which is applying f n times to the initial value 1. So you can use divide-and-conquer like the previous problem. Luckily, the composition of two linear functions is also linear. You can represent a linear function by three integers (the two constants and the modulus). Write a function that takes a linear function and an exponent and returns the function composed that many times.

Categories

Resources