I have a programming competition coming up and I am solving last years problems as revision for the competition, i came across a simple program however it requires math which unfortunately i am very bad at.
Here is the question:
Given a positive integer n,find the odd integer o and the
non-negative integer p such that n=o2^p (o multiplied by 2
to the power p)
the first line of the input file contains exactly one positive integer
d equal to the number of test cases,1<=d<=10. the data set follows. Each data set consists of exactly one line containing
exactly one integer n, 1<=n<=10^6
Sample output
2 //d value of number of test cases
24 // value of n
27 // value of n
Sample output
3 3 // first 3 is value of o, 2nd 3 is value of p
7 7 // first 7 is value of o, 2nd 7 is value of p
the "//" part should not be in the output or input
and this is what I have done so far, I got everything right except for the formula I need to use for the equation to solve correctly
public static void main(String[] args) {
double n = 0, d = 0, o = 0, p = 0;
double x = 1;
//START INPUT
Scanner input = new Scanner(System.in);
//input d, number of times program repeats
System.out.println("Please enter the number of times you want to run the test(no more than 10)");
d = input.nextDouble();
//check the validity of d
while((d > 10) || (d<1)){
System.out.println("Invalid input");
System.out.println("Enter another value for d");
d = input.nextDouble();
}
while(x <= d){
x++;
System.out.println("enter a value for n");
n = input.nextDouble();
//check the validity of n
while((n > 1000000) || (n<1)){
System.out.println("Invalid input.");
System.out.println("Enter Another Value for n");
n = input.nextDouble();
}
//Calculates
p = Math.log(n) / Math.log(2.0);
o = n / Math.pow(p, 2);
//STOP CALCULATE
//PRINTS
System.out.println(o + " " + p);
}
}
Any help is appreciated.
All you need to do is repeatedly divide by 2:
function removeTwo(n)
o, p := n, 0
while o % 2 == 0
o, p := o/2, p+1
return o, p
I'll leave it to you to translate to Java.
Many different ways. For programming contests I usually go with a simple approach when there are small numbers: bruteforce! Maybe not a perfect answer to your question, but keep it in mind when doing other tasks at the competition: working is good enough, choose the first solution you can come up with and try implementing it. At least that's true for most competitions I've been at, where it's about doing as many tasks as possible within a given time frame.
For the formula n = o2p,
with o odd and p > 0, and 1 <= n <= 106,
we can see that 2p will always be at least 2.
That means that o should be below half of n, so we only need to search for o's up to half of the value we're given. And we only need to check odd values.
And then one can just try different p values for the chosen o. If the result is higher than n, we should try the next value of o.
javacode:
public void calc(int n) {
for (int o = 1; o <= n / 2; o += 2) {
int p = 1;
while (true) {
int test = o * (int) Math.pow(2, p);
if (test == n) { // solution found
System.out.println("o:" + o + ", p:" + p);
return;
}
if (test > n) break; // total value too high, lets start with another o
p++;
}
}
}
Stepping through this with you input of n=24:
o = 1, p = 1 => 2
o = 1, p = 2 => 4
o = 1, p = 3 => 8
o = 1, p = 4 => 16
o = 1, p = 5 => 32, too high, try another o
o = 3, p = 1 => 6
o = 3, p = 2 => 12
o = 3, p = 3 => 24, TADA!
Different bruteforce methods may be to instead start with the value of p, or to instead divide n by different values of 2p until you get an odd integer.
The problem actually does not involve sooo much math. It's rather about bit twiddling.
It helps to know that each value 2^p is equal to (1<<p). Knowing this, you can first compute the highest bit that is set in n. For example
n = 24 = 11000 (binary) : Highest bit is 4
n = 36 : 100100 (binary) : Highest bit is 5
Then you can start with this bit position as a candiate for p, decrease this value until you find that the equation is solvable. When you reach zero, then the input value n must have been odd. This could be detected explicitly at the beginning, if desired.
import java.util.Arrays;
public class FindFactors
{
public static void main(String[] args)
{
for (int n=0; n<100; n++)
{
System.out.println("For "+n+" : "+Arrays.toString(findFactors(n)));
}
}
private static int[] findFactors(int n)
{
int p = highestBit(n);
while (p >= 0)
{
int twoPowP = (1 << p);
int c = n / twoPowP;
if (c * twoPowP == n)
{
return new int[]{c,p};
}
p--;
}
return null;
}
private static int highestBit(int n)
{
int b = 0;
while (n > 1)
{
n >>= 1;
b++;
}
return b;
}
}
Related
I was trying to figure out a way to calculate modulo inverse using java so I wrote this function to do it:
public static int privatekey(int primeprod, int e, int lambda)
{
Random random = new Random();
float d = 0;
//extended euler's theorem is
//d = (1 + x*lambda) / e
//d is smaller than primeprod
while(true)
{
int d = random.nextInt(200) + 1;
System.out.println("seed: "+x);
var = (1 + (x*lambda)) / e;
System.out.println("var: "+d);
if(isInteger(d) && d < primeprod)
{
break;
}
}
int finalvar = (int)d;
return finalvar;
}
I felt that it was going wrong so I reversed euclidean theorem extension I used above as follows
1 + x.lambda
------------- = d (this one is the equation to find out d when x is any integer)
e
de = 1 + x.lambda
de - 1 = x.lambda
de - 1
------- = x (this one is to check whether the value obtained by the above equation is true or not by checking if x is the same value we had chosen for our calculation in the first place)
lambda
After doing this check I found that the value of x I obtained in the reversed equation I had solved to check for mistakes is not equal but approximate to the original random value which I had generated.
For example taking these values:
e = 327
lambda = 484
x = 76
We get d as 112.0
later We reverse The equation to find the value of x to confirm
we get:
x = 75.667355372 (Which is approximate to the original value)
I wasn't able to figure out where it was going wrong.
To look at the full program please visit this link.
Please tell me If I have done something wrong here.
Thank You in advance!
Alright I got an answer to this problem.
The Issue was I was performing arithmetic operations on integer so the value I got as result was an integer.
Instead of using integer I later used Double to do the same operation and I resolved the issue.
public static int privatekey(Double primeprod, Double e, Double lambda)
{
Random random = new Random();
float d = 0;
//extended euler's theorem is
//d = (1 + x*lambda) / e
//d is smaller than primeprod
while(true)
{
int d = random.nextInt(200) + 1;
System.out.println("seed: "+x);
var = (1 + (x*lambda)) / e;
System.out.println("var: "+d);
if(isInteger(d) && d < primeprod)
{
break;
}
}
int finalvar = (int)d;
return finalvar;
}
This resolved the issue.
There are n stairs, a person standing at the bottom wants to reach the top. The person can climb either 1 stair or 2 stairs at a time.
Now I want to find the minimum number of steps needed that are divisible by given number m.
Here is the java program which I created using this as a reference, which is used to print the possible steps:
public static void main(String args[]) {
int n = 10, m = 2;
List<Integer> vals = new ArrayList<>();
Set<String> set = new TreeSet<>(Comparator.reverseOrder());
ClimbWays(n, 0, new int[n], vals, set);
set.forEach(a -> {
System.out.println(a + " : " + a.length());
});
}
public static void ClimbWays(int n, int currentIndex, int[] currectClimb, List<Integer> vals, Set<String> set) {
if (n < 0)
return;
if (n == 0) {
vals.add(currentIndex);
int last = 0;
StringBuilder sb = new StringBuilder();
for (int i = currentIndex - 1; i >= 0; i--) {
int current = currectClimb[i];
int res = current - last;
last = current;
sb.append(res);
}
String s = sb.toString();
char[] c = s.toCharArray();
Arrays.sort(c);
s = new String(c);
set.add(s);
return;
}
currectClimb[currentIndex] = n;
ClimbWays(n - 1, currentIndex + 1, currectClimb, vals, set);
ClimbWays(n - 2, currentIndex + 1, currectClimb, vals, set);
}
Output of the program is :
22222 : 5
112222 : 6
1111222 : 7
11111122 : 8
111111112 : 9
1111111111 : 10
Now for steps 10 if I want to get minimum steps divisible by m = 2, then the solution is 112222 which has 6 as the number of steps needed.
This program basically finds all possible pairs then add them to tree set. Next, I can loop through this set and get the minimum element divisible by given input m.
Is there a better approach to do this?
Since the person can climb a maximum of 2 steps at a time, the minimum number of steps to climb n stairs is
x = n/2 if n is even
x = n/2 + 1 if n is odd
Now you need to find the minimum number of steps to climb n stairs which is divisible by m. Meaning you need to find a number immediate next to x which is divisible by m.
if x%m == 0 then x is your answer
if x%m != 0 then ((x/m) + 1) * m is your answer.
Now speaking of your example
For n = 10,
x = n/2 = 5,
x%m = 5 % 2 = 1 != 0
Thus ans = ((5/2) + 1) * 2 = 6
For this lab, you will enter two numbers in base ten and translate
them to binary. You will then add the numbers in binary and print out
the result. All numbers entered will be between 0 and 255, inclusive,
and binary output is limited to 8 bits. This means that the sum of the
two added numbers will also be limited to 8 bits. If the sum of the
two numbers is more than 8 bits, please print the first 8 digits of
the sum and the message "Error: overflow". Your program should
represent binary numbers using integer arrays, with the ones digit
(2^0) stored at index 0, the twos digit (2^1) stored at index 1, all
the way up to the 2^7 digit stored at index 7. Your program should
include the following methods:
int[] convertToBinary(int b) Translates the parameter to a binary value and returns it stored as an array of ints.
void printBin(int b[]) Outputs the binary number stored in the array on one line. Please note, there should be exactly one space
between each output 0 or 1.
int[] addBin(int a[], int b[]) Adds the two binary numbers stored in the arrays, and returns the sum in a new array of ints.
When entering my code into CodeRunner (which tests the code and returns a grade back depending on the results of each test) I cannot seem to pass one of the tests. This is the message that I am getting:
*You had 43 out of 44 tests pass correctly. Your score is 97%.
The tests that failed were: Test: addBin() method Incorrect: Incorrect number returned*
Heres my code:
import java.util.Scanner;
class Main {
public static int[] convertToBinary(int a) {
int[] bin = {0, 0, 0, 0, 0, 0, 0, 0};
for (int i = bin.length - 1; i >= 0; i--) {
bin[i] = a % 2;
a = a / 2;
}
return bin;
}
public static void printBin(int[] b) {
int z;
for (z = 0; z < b.length; z++) {
System.out.print(b[z] + " ");
}
System.out.println();
}
public static int[] addBin(int[] c, int[] d) {
int[] added = new int[8];
int remain = 0;
for (int x = added.length - 1; x >= 0; x--) {
added[x] = (c[x] + d[x] + remain) % 2;
remain = (c[x] + d[x] + remain) / 2;
}
if (added[0] + c[0] + d[0] == 1) {
added[0] = 1;
} else if ((added[0] + c[0] + d[0] == 2) || (added[0] + c[0] + d[0] == 3)) {
System.out.println("Error: overflow");
}
return added;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Enter a base ten number between 0 and 255, inclusive.");
int num1 = scan.nextInt();
System.out.println("Enter a base ten number between 0 and 255, inclusive.");
int num2 = scan.nextInt();
int[] bin;
bin = convertToBinary(num1);
System.out.println("First binary number:");
printBin(bin);
int[] bin1 = bin;
bin = convertToBinary(num2);
System.out.println("Second binary number:");
printBin(bin);
int[] bin2 = bin;
System.out.println("Added:");
{
printBin(addBin(bin1, bin2));
}
}
}
If anyone could take a look at my code above and see if they could tell me what needs to be changed to fix the addbin() method so that it passes all of the tests, that'd be great! Any help is greatly appreciated even if you are not sure it would work! Thanks!
Hi first of all pardon my English but i guess your assignment accepts 1 and 255 too. So i added two of them and get 1 0 0 0 0 0 0 0 in your code. But i think it need to be 0 0 0 0 0 0 0 0 with an overflow error. So i changed your code a little bit.
public static int[] addBin(int[] c, int[] d) {
int[] added = new int[8];
int remain = 0;
for (int x = added.length - 1; x >= 0; x--) {
added[x] = (c[x] + d[x] + remain) % 2;
remain = (c[x] + d[x] + remain) / 2;
}
if (remain!=0) {
System.out.println("Error: overflow");
}
return added;
}
It's my first answer on the site so i hope it works for your test
I'm writing a java program that will find the GCD (greatest common divisor) of a number N. The program should evaluate some algebraic expression. lemme explain it further;
1. Calculate √(N)
2. Divide the result of (1) above by 18.
3. Compute the ceiling function of step(2) above and call it f. In other words, f = ceiling function of [√(N) divided by 18].
4. Set up the following three algebraic expressions in x and execute them sequentially from (a) to (c):
a) H1(x) = (N -1-18x ), x will take values from zero to f.
For each x, compute the gcd of H1(x) and N. Let’s call this gcd, d.
That is, d= gcd (N, H1(x)) or ( N, H1(x)).
If d =1, increase x by 1 and continue to do so until d > 1 or you come to x = f.
If d > 1, you have found one nontrivial divisor of N. Call it q. The other divisor of N is the value of H1(x) divided by q plus 1. Let’s call it p. Therefore, p = ( +1).
Then state that the divisors of N are p and q. Then prompt for another N to be entered or ask if the user wants to enter another N to be tested- with a Y/N option.
But if you could not find a gcd > 1 for H1(x) between x = 0 and x = f, move to (b) below:
b) H2(x) = (N -11-18x ), x will range from zero to f.
For each x, compute the gcd of H2(x) and N. Let’s call this gcd, d. That is,
d= gcd(N, H2(x)) or ( N, H2(x)).
If d =1, increase x by 1 and continue to do so until d > 1 or you come to x = f.
If d > 1, you have found one nontrivial divisor of N. Call it q. The other divisor of N is the value of H2(x) divided by q. Let’s call it p.
Therefore, p = ( +1).
Then state that the divisors of N are p and q. Then prompt for another N to be entered or ask if the user wants to enter another N to be tested- with a Y/N option.
But if you could not find a gcd > 1 for H2(x) between x = 0 and x = f, move to (c) below:
c) H4(x) = (N -13-18x ), x will range from zero to f.
For each x, compute the gcd of H4(x) and N. Let’s call this gcd, d.
If d =1, increase x by 1 and continue to do so until d > 1 or you come to x = f.
If d > 1, you have found one nontrivial divisor of N. Call it q. The other divisor of N is the value of H4(x) divided by q. Let’s call it p.
Therefore, p = ( +1).
Then state that the divisors of N are p and q.
See what I've done so far;
public static void main(String[] args) {
int num;
double sqrtnum;
double dividedsqrtnum;
double f;
int x = 0;
float a;
int d;
float p;
int q;
Scanner input = new Scanner(System.in);
System.out.println("Enter the number 'N'");
num = input.nextInt();
if( (num % 3) != 0){
System.out.println( "The number you entered is a semi-prime");
sqrtnum = Math.sqrt(num);
dividedsqrtnum = sqrtnum / 18;
f = Math.ceil(dividedsqrtnum) ;
System.out.println("The value of f is " + f);
// Algebraic expressions
for (x=0; x <= f; x++){
while (d == 1 || x ==f){
a = (num - 1 - 18 * x);
d = findGCD(num,a);
if ( d == 1){
x = x++;
}
else{
q = d;
p = (a / q + 1);
System.out.println("The divisors of "+ num +" are "+ p +" and " + q +" do you want to test another number? Y or N " );
}
}
}
}
else{
System.out.println("The number is not a semi-prime");
}
}
private static int findGCD(float num,float a) {
//base case
return findGCD(a, num%a);
}
}
Help me guys, I'm really stuck.
Problem: Given A,B print the number of pairs (a,b) such that GCD(a,b)=1 and 1<=a<=A and 1<=b<=B.
Solution (Brute Force Approach)
In the below code, i have used brute force approach and it works fine. However the execution time is more 10 sec if A & B > 10^5
Alternative Solution
From my research i found out that finding prime factors of A & B will reduce the execution time considerably (< 3 sec), but i'm not sure how to apply it.
Need Help:
Can anyone help me to arrive at the result with < 3 sec execution time?
class GCD {
public static void main(String[] args) {
int A = 0, B = 0, GCD = 0, count = 0;
BigInteger B1, B2 = null;
A = Integer.parseInt(args[0]);
B = Integer.parseInt(args[1]);
for (int a = 1; a <= A; a++) {
for (int b = 1; b <= B; b++) {
B1 = BigInteger.valueOf(a);
B2 = BigInteger.valueOf(b);
GCD = calculateGCD(B1, B2);
if (GCD == 1) {
count++;
}
}
}
System.out.println(count);
}
public static int calculateGCD(BigInteger number1, BigInteger number2) {
return (number1.gcd(number2)).intValue();
}
}
I do not want to write a complete programm or something, but I want to give you some tips for speeding up your program:
gcd(a,b) = gcd(b,a) so only compute pairs (a, b) with a < b. gcd(a,a) = 1 holds only for a = 1. Also gcd(1,b) = 1 for all b, so you can start with a = 2 and a count = 1 + 2*(B-1).
compute all primefactors for all 1 < a <= A at once by using something like the Sieve of Eratosthenes. E.g. every secound number contains primefactor 2, every third the primfactor 3.
You do not need to compute the gcd. Let a contain the distinct primfactors p and q. Then you know:
There are B-a numbers to test.
Every p-th number contains also the primfactor p, every q-th primenumber also contains the primfactor q. floor( (B-a)/p ) numbers have a gcd >= p and floor( (B-a)/q ) numbers have a gcd >= q and floor( (B-a)/(p*q) ) numbers have you counted twice. So you can get the number of pairs (a,b) with a < b as
(B-a) - floor( (B-a)/p ) - floor( (B-a)/q ) + floor( (B-a)/(p*q) )
if you want also the pairs it self, you can use a for-loop and jump every step where i (for-loop counter) is divisable by any primefactor of a
I think this should speed up your program as much as you need to reach less than a second.