简体   繁体   中英

A program that will solve a log math prob, using Java

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 = o2 p , with o odd and p > 0, and 1 <= n <= 10 6 , we can see that 2 p 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 2 p 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;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM