Calculating 2^n%k using only integers - java

I need to write a code that gets 2 variables (n,k) and prints the answer to (2^n)%k.
I can use integers only, no methods, no arrays, no math. and so on.
so far i have this:
int n = myScanner.nextInt();
int k = myScanner.nextInt();
int num = 1;
int modulo = 1;
for (int i = 0; i < n; i++) {
num = num * 2;
modulo *= 2%k;
}
modulo = modulo%k;
System.out.println(modulo);
the problem is the range of the int itself, doesn't go more than 2^31... but still i need to make it work somehow, any help would be really appreciated!

You are dealing with Modular exponentiation. One possible solution is to avoid multiplication on large numbers, that will overflow the int, by taking advantage of below:
Given two integers a and b, the following two equations are equivalent:
c mod m = (a ⋅ b) mod m
c mod m = [(a mod m) ⋅ (b mod m)] mod m
In Java a simple solution based on algorithm explained in this section:
int mod(int base, int exponent, int modulus) {
if (modulus == 1) return 0;
int c = 1;
for (int i = 0; i < exponent; i++) {
c = (c * base) % modulus;
}
return c;
}

If your problem is that it can't store more than 2^31 it's because you need to use a long datatype to store the value. A long can store a maximum value of 2^63 (signed).

Related

Java: Expression including binomial coefficient calculation

Task is to calculate expression for natural numbers entered.
I know I should calculate binominal coefficient here right?
Also I know that (-1)^p determines whether this array is decrementing or incrementing, but don't know how to use p in my code
I am not quite sure how to put it all together, this is what I came up with so far and it is really nothing special as I still can't grasp on the idea of how to write this in program.
public static int calculateExpression(int n, int k,int p) {
if(k<0 || n<k)
{
return 0;
}
// Find factorial of n
int n_fac = 1;
for (int j = 1; j <= n; j++) {
n_fac = n_fac * j;
}
// Find factorial of k
int k_fac = 1;
for(int i = 1; i<=k; i++) {
k_fac = k_fac * i;
}
// Find n-k fac
int n_k = n-k;
int n_k_fac = 1;
for(int l = 1; l<=n_k;l++) {
n_k_fac*=l;
}
// n/k = n!/k!(n-k)!
double resultOf_n_kDivision = n_fac/k_fac*n_k_fa;
System.out.println(resultOf_n_kDivision);
return n_k_fac;
}
The factorial function is a very fast-growing one, so calculating the numerator and denominator separately may not be a good idea, as it may lead to overflow for even relatively small values of n.
Let's look at an iterative method for calculating the coefficient:
We see that we can calculate the next coefficient of the row if we know the current one. Thus we can incrementally calculate each term in S, while being less concerned about overflow problems.
static int calculateExpression(int n, int k, int p)
{
// first term of the row is (n, 0) = 1
int binom = 1;
// Iteratively find (n, k)
for (int i = 0; i < k; i++)
binom = (binom * (n - i)) / (i + 1);
// sum the series
int S = binom;
for (int i = 0; i < p; i++) {
// "trick": multiply with a minus sign each time to flip the sign
binom = (-binom * (n - k - i)) / (k + i + 1);
S += binom;
}
return S;
}
UPDATE: Parallel numerical tests:
n k p | orig new
----------------------
5 3 2 | 6 6
10 4 1 | -42 -42
12 3 7 | 44 44
15 8 6 | 3433 8 // integer overflow occurred with the original method
As you can see the two functions were consistent until the last line with n = 15, as 15! = 1307674368000 is much bigger than the maximum positive value of int in most implementations of Java (32-bit).
Use abstraction for better tackling problems; define fac and over.
Then the problem becomes:
public static int calculateExpression(int n, int k,int p) {
int sum = 0;
int minus1toP = 1;
for (int i = 0; i <= p; i++) {
sum += minus1toP * over(n, ...);
minus1toP = -minus1toP;
}
return sum;
}
static int over(int n, int k) {
return fac(n) / fac(k) / fac(n - k);
}
static int fac(int n) {
int f = 1;
for(int i = 2; i <= n; i++) {
f *= i;
}
return f;
}
I did not give the entire solution (...), but maybe too much already.
I did not really get your question, but you can just use this.
public static double combination(int n, int k)
{
double nFactorial = getFactorialFromNToK(n, k);
double kFactorial = getFactorialFromNToK(k, 1);
return nFactorial / kFactorial;
}
public static double getFactorialFromNToK(double n, double k)
{
double factorial = 1;
for (; n - k + 1 > 0; n--)
{
factorial *= n;
}
return factorial;
}
This is the evaluation of nCk for the coef of a term in the binomial expansion.
If nCn is a term in the expansion, then it converges and if it does not exist as term in the expansion, then it will not converge. So if it is a natural number expansion, then it will always converge.
A better solution is to use the lngamma function instead of factorial. It's a more efficient way to calculate factorials. The natural log means that dividing large numbers will be less of a problem.

How to write Extended Euclidean Algorithm code wise in Java?

I have a question which is actually requires a bit of understanding Euclidian Algorithm. Problem is simple. An int "First" and int "Second" numbers are given by the user via Scanner.
Than we need to find greatest common divisor of them. Than the process goes like explained below:
Now Assume that the First number is: 42 and the Second is: 30 - they've given by the user. -
int x, y;
(x * First) + (y * Second) = gcd(First, Second); // x ? y ?
To Find GCD you may use: gcd(First, Second); Code is below:
public static int gcd(int a, int b)
{
if(a == 0 || b == 0) return a+b; // base case
return gcd(b,a%b);
}
Sample Input: First: 24 Second: 48 and Output should be x: (-3) and y: 2
Sample Input: First: 42 Second: 30 and Output should be x: (-2) and y: 3
Sample Input: First: 35 Second: 05 and Output should be x: (0) and y: 1
(x * First) + (y * Second) = gcd(First, Second); // How can we find x and y ?
I would very appreciate it if you could show a solution code wise in java thanks for checking!
The Extended Euclidean Algorithm is described in this Wikipedia article. The basic algorithm is stated like this (it looks better in the Wikipedia article):
More precisely, the standard Euclidean algorithm with a and b as
input, consists of computing a sequence q1,...,
qk of quotients and a sequence r0,...,
rk+1 of remainders such that
r0=a r1=b ...
ri+1=ri-1-qi ri and 0 <
ri+1 < |ri| ...
It is the main property of Euclidean division that the inequalities on
the right define uniquely ri+1 from ri-1 and
ri.
The computation stops when one reaches a remainder rk+1
which is zero; the greatest common divisor is then the last non zero
remainder rk.
The extended Euclidean algorithm proceeds similarly, but adds two
other sequences defined by
s0=1, s1=0 t0=0,
t1=1 ...
si+1=si-1-qi si
ti+1=ti-1-qi ti
This should be easy to implement in Java, but the mathematical way it's expressed may make it hard to understand. I'll try to break it down.
Note that this is probably going to be easier to implement in a loop than recursively.
In the standard Euclidean algorithm, you compute ri+1 in terms of ri-1 and ri. This means that you have to save the two previous versions of r. This part of the formula:
ri+1=ri-1-qi ri and 0 <
ri+1 < |ri| ...
just means that ri+1 will be the remainder when ri-1 is divided by ri. qi is the quotient, which you don't use in the standard Euclidean algorithm, but you do use in the extended one. So Java code to perform the standard Euclidean algorithm (i.e. compute the GCD) might look like:
prevPrevR = a;
prevR = b;
while ([something]) {
nextR = prevPrevR % prevR;
quotient = prevPrevR / prevR; // not used in the standard algorithm
prevPrevR = prevR;
prevR = nextR;
}
Thus, at any point, prevPrevR will be essentially ri-1, and prevR will be ri. The algorithm computes the next r, ri+1, then shifts everything which in essence increments i by 1.
The extended Euclidean algorithm will be done the same way, saving two s values prevPrevS and prevS, and two t values prevPrevT and prevT. I'll let you work out the details.
Thank's for helping me out ajb I solved it after digging your answer. So for the people who would like to see code wise:
public class Main
{
public static void main (String args[])
{
#SuppressWarnings("resource")
System.out.println("How many times you would like to try ?")
Scanner read = new Scanner(System.in);
int len = read.nextInt();
for(int w = 0; w < len; w++)
{
System.out.print("Please give the numbers seperated by space: ")
read.nextLine();
long tmp = read.nextLong();
long m = read.nextLong();
long n;
if (m < tmp) {
n = m;
m = tmp;
}
else {
n = tmp;
}
long[] l1 = {m, 1, 0};
long[] l2 = {n, 0, 1};
long[] l3 = new long[3];
while (l1[0]-l2[0]*(l1[0]/l2[0]) > 0) {
for (int j=0;j<3;j++) l3[j] = l2[j];
long q = l1[0]/l2[0];
for (int i = 0; i < 3; i++) {
l2[i] = (l1[i]-l2[i]*q);
}
for (int k=0;k<3;k++) l1[k] = l3[k];
}
System.out.printf("%d %d %d",l2[1],l2[2],l2[0]); // first two Bezouts identity Last One gcd
}
}
}
Here is the code that I came up with if anyone is still looking. It is in C# but I am sure it similar to java. Enjoy
static void Main(string[] args)
{
List<long> U = new List<long>();
List<long> V = new List<long>();
List<long> W = new List<long>();
long a, b, d, x, y;
Console.Write("Enter value for a: ");
string firstInput = Console.ReadLine();
long.TryParse(firstInput, out a);
Console.Write("Enter value for b: ");
string secondInput = Console.ReadLine();
long.TryParse(secondInput, out b);
long temp;
//Make sure that a > b
if(a < b)
{
temp = a;
a = b;
b = temp;
}
//Initialise List U
U.Add(a);
U.Add(1);
U.Add(0);
//Initialise List V
V.Add(b);
V.Add(0);
V.Add(1);
while(V[0] > 0)
{
decimal difference = U[0] / V[0];
var roundedDown = Math.Floor(difference);
long rounded = Convert.ToInt64(roundedDown);
for (int i = 0; i < 3; i++)
W.Add(U[i] - rounded * V[i]);
U.Clear();
for (int i = 0; i < 3; i++)
U.Add(V[i]);
V.Clear();
for (int i = 0; i < 3; i++)
V.Add(W[i]);
W.Clear();
}
d = U[0];
x = U[1];
y = U[2];
Console.WriteLine("\nd = {0}, x = {1}, y = {2}", d, x, y);
//Check Equation
Console.WriteLine("\nEquation check: d = ax + by\n");
Console.WriteLine("\t{0} = {1}({2}) + {3}({4})", d, a, x, b, y);
Console.WriteLine("\t{0} = {1} + {2}", d, a*x, b*y);
Console.WriteLine("\t{0} = {1}", d, (a * x) + (b * y));
if (d == (a * x) + (b * y))
Console.WriteLine("\t***Equation is satisfied!***");
else
Console.WriteLine("\tEquation is NOT satisfied!");
}
}
}

Java: avoiding factorial overflow

I'm supposed to optimize the following code so that it calculates the central binomial coefficient up to the max value of integer (up to n = 16).
public static int factorial(int n)
{
int result= 1;
for(int i = 2; i <= n; i++) result *= i;
return result;
}
public static int centralbinom(int n)
{
return factorial(2*n) / (factorial(n) * factorial(n));
}
Naturally I get an overflow for every n > 6.
How do I 'break down' the factorial function so that doesn't has to deal with big numbers such as 2n = 2*16 = 32 ?
Or is there a better way to calculate the central binomial coefficient?
Here are several optimizations that you can do in addition to using BigIntegers that may reduce your calculations, in most of you cases overflow that you may be having in your program.
Since you need factorial(n) at least two time. Calculate it once and store it in a variable.
Factorial(2*n) has factorial(n) in it. Since you have already calculated factorial(n) before all you need to do is calculate till factorial(2n....n) and then multiply factorial(n) to it. Here's one way how that can be done.
//Pseudocode
//find factorial of n given I know already till k
int findFactorial(n, k) {
int result = 1
for i n to 1
if(i==k)
break;
result = result * n;
return result
}
//factorial(2*n) = facorial(n, k) * factorial(k)
This will reduce your calculations a lot and in case if you expect your program not to have an overflow, you can go away with BigIntegers.
If you need a factorial of big number, you have to use BigInteger class to calculate result:
public static BigInteger factorial(int n) {
BigInteger result = BigInteger.ONE;
for (int i = 2; i <= n; ++i) {
result = result.multiply(BigInteger.valueOf(i));
}
return result;
}
If the central binomial coefficient of 17 is greater than the integer max, and you only need to compute it for 17 numbers, then the obvious solution is a lookup table. Create a 17-element array containing the central binomial coefficient for n = 0 to 16. I think you'll find this solution is extremely efficient.
You can find a list of them here. http://oeis.org/A000984
Just compress your factorial by gamma.
set gamma to 10 is good enough
public static double factorial(int n, double gamma)
{
double result= 1;
double gammaInv = 1.0/gamma;
for(int i = 2; i <= n; i++) result *= pow(i,gammaInv);
return result;
}
public static int centralbinom(int n, double gamma)
{
return pow(factorial(2*n,gamma) /
(factorial(n,gamma) * factorial(n),gamma),
gamma);
}

Why java.Math.BigInteger bugs out after a certain limit?

Am trying to print the sum of digits in 2^n for n = 1 to 1000.
Here's what I've done.
public static void main(String[] args) {
int n = 1000;
for (int i = 1; i < n; i++) {
BigInteger power = BigInteger.valueOf((int)Math.pow(2, i));
int sum = 0;
while (power.intValue() > 0) {
sum += power.intValue() % 10;
power = power.divide(BigInteger.valueOf(10));
}
System.out.print(sum + " ");
}
}
It works only till about 2^30 or so and then prints the same result, 46, for the rest.
I tried a similar thing using "long long" in C and that printed 0's after a similar limit.
According to the answers, I changed
BigInteger power = BigInteger.valueOf((int)Math.pow(2, i));
to
BigInteger power = BigInteger.valueOf(2).pow(i);
and 46 changed to 0. Just like C.
Still not working...
You're using Math.pow to generate the value you should use the BigInteger functions to do so instead.
The sum should be stored in a BigInteger as well not an int.
You are doing integer arithmetic and then putting it into a biginteger. Use a biginteger's pow method instead.
Because you aren't using BigInteger.
Computing numbers using BigInteger doesn't let you magically store their sum in an int.
Similarly, passing an int to BigInteger.valueOf() doesn't magically make that int bigger.
You're calling Math.pow() with regular integers, not BigIntegers. You're calling it on integer literals.
You want this:
int i = 7; //or whatever power
BigInteger k = BigInteger.valueOf(2);
k = k.pow(i);

Sum of two numbers with bitwise operator

I am pasting the code to find the sum of two numbers with bitwise operator. Please suggest if it can be optimized. Thanks...
public static int getSum(int p, int q)
{
int carry=0, result =0;
for(int i=0; i<32; i++)
{
int n1 = (p & (1<<(i)))>>(i); //find the nth bit of p
int n2 = (q & (1<<(i)))>>(i); //find the nth bit of q
int s = n1 ^ n2 ^ carry; //sum of bits
carry = (carry==0) ? (n1&n2): (n1 | n2); //calculate the carry for next step
result = result | (s<<(i)); //calculate resultant bit
}
return result;
}
Think in entire bits:
public static int getSum(int p, int q)
{
int result = p ^ q; // + without carry 0+0=0, 0+1=1+0=1, 1+1=0
int carry = (p & q) << 1; // 1+1=2
if (carry != 0) {
return getSum(result, carry);
}
return result;
}
This recursion ends, as the carry has consecutively more bits 0 at the right (at most 32 iterations).
One can easily write it as a loop with p = result; q = carry;.
Another feature in algorithmic exploration is not going too far in differentiating cases.
Above you could also take the condition: if ((result & carry) != 0).
I think that the optimizations should be in the field of readability, rather than performance (which will probably be handled by the compiler).
Use for loop instead of while
The idiom for (int i=0; i<32; i++) is more readable than the while loop if you know the number of iterations in advance.
Divide the numbers by two
Dividing the numbers by two and getting the modulu:
n1 = p % 2;
p /= 2;
Is perhaps more readable than:
(p & (1<<(i-1)))>>(i-1);
I think below soln is easy to understand & simple,
public static void sumOfTwoNumberUsingBinaryOperation(int a,int b)
{
int c = a&b;
int r = a|b;
while(c!=0)
{
r =r <<1;
c = c >>1;
}
System.out.println("Result:\t" + r);
}

Categories

Resources