Given integers N and M, find the number of ordered pairs (a, b) such that 1≤a <b≤N and ((M mod a) mod b) = ((M mod b) mod a).
Input
The first line contains an integer T, the number of test cases. Then the test cases follow.
The only line of each test case contains two integers N, M.
output
For each test case, output in a single line the answer to the problem.
Constraints
1≤T≤1000
2≤N≤10 ^ 6
1≤M≤5⋅10 ^ 5
The sum of N over all test cases does not exceed 10 ^ 6
I have tried O (N ^ 2) approach but it gives TLE. Need a new approach or any idea
import java.util.Scanner;
class test {
public static void main(String[] args) {
try {
Scanner scn = new Scanner(System.in);
int testCase = scn.nextInt();
for (int i = 0; i < testCase; i++) {
int n = scn.nextInt();
int m = scn.nextInt();
int count = 0;
for (int j = 1; j < n; j++) {
for (int k = j + 1; k <= n; k++) {
if (((m % j) % k) == ((m % k) % j)) {
// System.out.print(j+" "+k);
// System.out.println();
count++;
}
}
}
System.out.println(count);
}
} catch (Exception e) {
return;
}
}
}
I can see some improvements. First of all, since a<b, (M mob a) mod b = M mod a
So we have to check whether M mod a = (M mod b) mod a, but this means that a divides (M - (M mod b))=((M div b) * b)
To sum up, we have to iterate over all b=1,...,n and for each of them we have to count the divisors of ((M div b) * b) which are less than b.
The improvement is the fact that ((M div b) * b) is comparable with b, and when we are looking for the divisor of ((M div b) * b) we can stop at its square root.
A possible implementation (in which I have removed the tests cases) is this one
class Test {
public static void main(String[] args) {
try {
Scanner scn = new Scanner(System.in);
int n = scn.nextInt();
int m = scn.nextInt();
int count = 0;
for (int j = 1; j < n; j++) {
for (int k = j + 1; k <= n; k++) {
if (((m % j) % k) == ((m % k) % j)) {
//System.out.print(j+" "+k);
//System.out.println();
count++;
}
}
}
System.out.println(count);
count=0;
for (int b = 1; b <= n; b++) {
//System.out.println((m/b)*b);
count += countDivisors(m, b);
}
System.out.println(count);
} catch (Exception e) {
return;
}
}
private static int countDivisors(int m, int b) {
int count=0;
int val = ((m/b)*b);
int mi = Math.min((int)Math.sqrt(val), b-1);
if(mi == 0)
return (b-1);
for(int a=1; a<=mi; a++) {
if(val % a == 0) {
count++;
int aa=val/a;
if(aa>a && aa < b) {
count++;
}
}
}
return count;
}
}
Related
I have a problem with creating a recursive method for finding Amicable numbers between 1 - 10000. I created a method to find out if two numbers are Amicable, but I don't know how to run it against every possible number combination. Here are both methods which I wrote.
public void amicable(int n, int m) {
int sumM = 0;
int sumN = 0;
for (int i = 1; i < n; i++) {
if (n % i == 0) {
sumN += i;
}
}
for (int j = 1; j < m; j++) {
if (m % j == 0) {
sumM += j;
}
}
if (sumN == m && sumM == n) {
System.out.println(n + " and " + m + " are amicable numbers");
}
}
public static void amicableBetween(int n, int m) {
int sumaM = 0;
int sumaN = 0;
if (m >= 1) {
for (int j = 1; j < m; j++) {
if (m % j == 0) {
sumaM += j;
}
}
for (int i = 1; i < n; i++) {
if (n % i == 0) {
sumaN += i;
}
}
if (sumaN == m && sumaM == n) {
System.out.println(n + " and " + m + " are amicable numbers");
amicableBetween(n + 1, m - 1);
} else {
System.out.println(n + " i " + m + " aren't amicable numbers");
amicableBetween(n + 1, m - 1);
}
}
}
}
Minor disclaimer, this method might take forever and you might run out of stack space so I'm not 100% sure that calculating all the amicable numbers from 1-10000 recursively is the way to go. If this is just for fun or practice then I guess is ok.
One approach will be to sweep n until we reach m - 1 and call amicable(n,m) in each step. Once n has reached m - 1, we can decrease m by 1 and repeat the process until n is equal to m - 1 then we have checked all possible combinations. To do this, you can break your two methods into three methods.
The first method is the amicable method you already have, just changed the return type so that we can reuse it while we are going down the recursion chain:
public static boolean amicable(int n, int m) {
int sumM = 0;
int sumN = 0;
for (int i = 1; i < n; i++) {
if (n % i == 0) {
sumN += i;
}
}
for (int j = 1; j < m; j++) {
if (m % j == 0) {
sumM += j;
}
}
return sumN == m && sumM == n;
}
The second will be the public method amicableBetween(int n, int m)
public static void amicableBetween(int n, int m) {
amicableBetween(n, m, true);
}
Which will call a third private helper method amicableBetween(int n, int m, boolean start) that has a third parameter start that it can use to identify if n has reached m. Then we need to decrease m by 1 and repeat the process:
private static void amicableBetween(int n, int m, boolean start) {
if(n == m) {
return;
}
if (m >= 1) {
if (amicable(n, m)) {
System.out.println(n + " and " + m + " are amicable numbers");
} else {
System.out.println(n + " and " + m + " aren't amicable numbers");
}
amicableBetween(n + 1, m, false);
}
if(start) {
amicableBetween(n, m - 1, true);
}
}
I wonder why do you want a recursive algorithm. Don't you warry about StackOvervlowException?! It is pretty easy to find with simple Map within O(n) time:
public static void amicable(int lo, int hi) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = lo; i <= hi; i++) {
int j = map.computeIfAbsent(i, DIV_SUM);
if (j > i && j <= hi && map.computeIfAbsent(j, DIV_SUM) == i)
System.out.format("[%d : %d]\n", i, j);
}
}
private static final Function<Integer, Integer> DIV_SUM = val -> {
int sum = 0;
for (int i = 1, max = val / 2; i <= max; i++)
if (val % i == 0)
sum += i;
return sum;
};
Demo: time ~150ms
amicable(1, 10000);
[220 : 284]
[1184 : 1210]
[2620 : 2924]
[5020 : 5564]
[6232 : 6368]
So, you wrote a method that can tell if two numbers are amicable. That's the hard part out of the way. All you have to do is call that from inside two loops, one for the upper bound, one for the lower bound.
for(lowerNumber = 1; lowerNumber < 10000; lowerNumber++){
for(upperNumber = lowerNumber + 1; upperNumber <= 10000; upperNumber++){
amicable(lowerNumber, upperNumber);
}
}
I'm not sure why you need two parameters in the amicable function. An amicable number has a repeating aliquot sequence of period 2, which means
s(s(n)) == n
We can find the number's complement by retrieving the sum of its proper divisors and checking the assertion above.
This means to find the amicable numbers for n between 1 and 10,000 we only need n, and would also make trivial the part of the process you seem to want as a recursion.
JavaScript code:
function s(n){
let s = n > 1 ? 1 : 0;
let sqrt_n = Math.sqrt(n);
let d1=Math.floor(n/2);
for (; d1>=sqrt_n; d1--){
let d2 = n / d1;
if (d2 == Math.floor(d2))
s += d1 + d2;
}
if (d1 == sqrt_n)
s += d1;
return s;
}
let n = 220;
let s_n = s(n);
if (s(s_n) == n)
console.log('Amicable!', n, s_n);
for my school project I have to create a program that outputs perfect numbers based on how many perfect numbers the user(teacher) want. The user can pick any number from 1-4 and it should display however many number the user chooses. Here is my current code. Please ignore the sumupTo, factorial, isprime, and the testGoldbach methods, please only look at the Perfect numbers method/code.
import java.util.Scanner;
public class MyMathB
{
public static int sumUpTo(int n)
{
int sum = 0;
for (int k = 1; k <= n; k++)
sum += k;
return sum;
}
public static long factorial(int n)
{
long f = 1;
for (int k = 2; k <= n; k++)
f *= k;
return f;
}
public static boolean isPrime(int n)
{
if (n <= 1)
return false;
int m = 2;
while (m * m <= n)
{
if (n % m == 0)
return false;
m++;
}
return true;
}
public static void PerfectNumbers(int number)
{
System.out.println("How many perfect numbers would you like to see? Please enter an integer from 1 to 4");
Scanner s = new Scanner(System.in);
int numbersToSee = s.nextInt();
int counts = 0;
for(counts = 0; counts <= numbersToSee; counts++)
{
for (int n = 5; n <= 10000; n++)
{
int temp = 0;
for(int i = 1; i <= number / 2; i++)
{
if (number % i == 0)
{
temp += i;
}
if (temp == number)
{
System.out.println(number);
}
}
}
}
}
public static boolean testGoldbach(int bigNum)
{
for (int n = 6; n <= bigNum; n += 2)
{
boolean found2primes = false;
for (int p = 3; p <= n/2; p += 2)
{
if (isPrime(p) && isPrime(n - p))
found2primes = true;
}
if (!found2primes)
{
System.out.println(n + " is not a sum of two primes!");
return false;
}
}
return true;
}
public static void main(String[] args)
{
Scanner kb = new Scanner(System.in);
int n;
do
{
System.out.print("Enter an integer from 4 to 20: ");
n = kb.nextInt();
} while (n < 4 || n > 20);
kb.close();
System.out.println();
System.out.println("1 + ... + " + n + " = " + sumUpTo(n));
System.out.println(n + "! = " + factorial(n));
System.out.println("Primes: ");
for (int k = 1; k <= n; k++)
if (isPrime(k))
System.out.print(k + " ");
System.out.println();
System.out.println("Goldbach conjecture up to " + n + ": " + testGoldbach(n));
}
}
you didn't declare the variable "number" in your method.
Edit: you didn't SET the variable number to anything, I misworded my last statement.
I'm trying to add the gcd() function to the NumericFunctions class and include code in main to compute gcd(m,n).
However, I keep getting an error:
Exception in thread "main" java.lang.StackOverflowError
at NumericFunctions.gcd(NumericFunctions.java:14)
Source code:
public class NumericFunctions {
public static long factorial(int n) {
long result = 1;
for (int i = 2; i <= n; i++) {
result *= i;
}
return result;
}
public static int gcd (int n, int m) {
if ((m % n) == 0)
return n;
else
return gcd(n, m % n);
}
public static void main(String[] args) {
for (int n = 1; n <= 10; n++)
for (int m = 1; m <= 10; m++){
System.out.println(gcd(n,m));
System.out.println(" ");
System.out.println(factorial(n));
}
}
}
Check out the following corrections in gcd() method:
public static int gcd (int n, int m) {
if ((n % m) == 0)
return m; // <-- first correction
else
return gcd(m, n % m); // <-- second correction
}
I am trying to do the following program in Java where I'm writing a recursive and an iterative method to compute the sum of all odd numbers from n to m
import java.util.Scanner;
public class AssignmentQ7 {
public static int recursivesum(int n, int m){
if (n < m){
int s = n;
s += recursivesum(n+2, m);
} else{
if(m < n){
int s = m;
s += recursivesum(m+2, n);
}
}
return s;
}
public static int iterativesum(int n, int m){
if(n < m){
int s = n;
for(int i = n; i <= m; i += 2){
s += i;
return s;
}
} else
if(m < n){
int s = m;
for(int i = m; i <= n; i += 2){
s += i;
return s;
}
}
}
public static void main(String args[]){
int n,m;
Scanner in = new Scanner(System.in);
System.out.println("Enter two numbers: ");
n = in.nextInt();
m = in.nextInt();
while(n%2 == 0){
System.out.println("Enter the first number again: ");
n = in.nextInt();
}
while(m%2 == 0){
System.out.println("Enter the second number again: ");
m = in.nextInt();
}
System.out.println("The answer of the recursive sum is: " + recursivesum(n,m));
System.out.println("The answer of the iterative sum is: " + iterativesum(n,m));
}
}
I'm getting an error cannot find symbol - variable enter code heres. I don't know what's wrong! Can anyone help please?
This method is the problem:
public static int recursivesum(int n, int m) {
if (n < m) {
int s = n; // Variable declared here... scoped to the if
s += recursivesum(n+2, m);
} else {
if (m < n) {
int s = m; // Variable declared here... scoped to this if
s += recursivesum(m+2, n);
}
}
return s; // No such variable in scope!
}
You could use:
public static int recursivesum(int n, int m) {
int s = 0; // See note below
if (n < m) {
s = n + recursivesum(n+2, m);
} else {
if (m < n) {
s = m + recursivesum(m+2, n);
}
}
return s;
}
We have to give s an explicit initial value, because you currently don't have any code handling the case where n and m are equal. It's not clear what you want to do then.
Another alternative is to return from the if statements, just as you do in iterativesum... although you'll again need to think about what to do if m == n:
public static int recursivesum(int n, int m) {
if (n < m) {
// You don't even need an s variable!
return n + recursivesum(n+2, m);
} else if (m < n) {
// Simplified else { if { ... } } to else if { .... }
return m + recursivesum(m+2, n);
} else {
// What do you want to return here?
}
}
Note that you've got the same problem in iterativesum - the compiler should be complaining at you at the moment that not all paths return a value. What do you expect iterativesum(3, 3) to do?
in recursivesum(int n, int m) method, you have declared s within if condition, but, you tried to access it in else part.
public static int recursivesum(int n, int m){
int s = n; // Now s having method local scope
if (n < m){
s += recursivesum(n+2, m);
} else{
if(m < n){
int s = m;
s += recursivesum(m+2, n);
}
}
return s;
}
In the recursivesum(int n,int m) function the scope of variable s is inside the if and else block. When your returning s it is out of scope.
Try using some IDE's like eclipse. So that you can debug these errors instantly
Try this:
int s;
if (n < m){
s = n;
s += recursivesum(n+2, m);
} else{
if(m < n){
int s = m;
s += recursivesum(m+2, n);
}
}
return s;
You are declaring variable s inside if statement, that is why you get such error. Start from declaration int s outside if statement.
your s is out of scope in recursivesum(int n, int m) method
Declare s outside the if-else block
It's scope problem. You're declaring variable s inside the if statements which is (local definition) of variable.
You need to modify the two methods as follows:
The recursive method will be
public static int recursivesum(int n, int m) {
int s = 0;
if (n < m) {
s = n;
s += recursivesum(n + 2, m);
} else {
if(m < n){
s = m;
s += recursivesum(m + 2, n);
}
}
return s;
}
And the iterative method will be:
public static int iterativesum(int n, int m) {
int s = 0;
if(n < m) {
s = n;
for(int i = n; i <= m; i += 2) {
s += i;
}
} else {
if(m < n) {
s = m;
for(int i = m; i <= n; i += 2) {
s += i;
}
}
}
return s;
}
You have an error in the first method where you define s outside the scope which you return it from. In the second method you return inside the loop.
As others in this thread suggests, use an IDE like Eclipse (https://www.eclipse.org/) or IntelliJ (http://www.jetbrains.com/idea/)
import java.util.Scanner;
public class AssignmentQ7 {
public static int recursivesum(int n, int m) {
int s = n;
if (n < m) {
s += recursivesum(n + 2, m);
}
else {
if (m < n) {
s = m;
s += recursivesum(m + 2, n);
}
}
return s;
}
public static int iterativesum(int n, int m) {
int s = 0;
if (n < m) {
for (int i = n; i <= m; i += 2) {
s += i;
}
}
else if (m < n) {
for (int i = m; i <= n; i += 2) {
s += i;
}
}
return s;
}
public static void main(String args[]) {
int n, m;
Scanner in = new Scanner(System.in);
System.out.println("Enter two numbers: ");
n = in.nextInt();
m = in.nextInt();
while (n % 2 == 0) {
System.out.println("Enter the first number again: ");
n = in.nextInt();
}
while (m % 2 == 0) {
System.out.println("Enter the second number again: ");
m = in.nextInt();
}
System.out.println("The answer of the recursive sum is: " + recursivesum(n, m));
System.out.println("The answer of the iterative sum is: " + iterativesum(n, m));
}
}
Your code must be like this, you dont have to use two for loop.
import java.util.Scanner;
public class AssignmentQ7 {
public static int recursivesum(final int n, final int m) {
final int lower = n < m ? n : m;
final int upper = n > m ? n : m;
final int total = lower;
if (lower >= upper) {
return total;
}
return total + AssignmentQ7.recursivesum(lower + 2, upper);
}
public static int iterativesum(final int n, final int m) {
final int lower = n < m ? n : m;
final int upper = n > m ? n : m;
int total = 0;
for (int num = lower; num <= upper; num = num + 2) {
total += num;
}
return total;
}
public static void main(final String args[]) {
int n, m;
final Scanner in = new Scanner(System.in);
System.out.println("Enter two numbers: ");
n = in.nextInt();
m = in.nextInt();
while (n % 2 == 0) {
System.out.println("Enter the first number again: ");
n = in.nextInt();
}
while (m % 2 == 0) {
System.out.println("Enter the second number again: ");
m = in.nextInt();
}
System.out.println("The answer of the recursive sum is: " + AssignmentQ7.recursivesum(n, m));
System.out.println("The answer of the iterative sum is: " + AssignmentQ7.iterativesum(n, m));
}
}
I've got to ensure that the GCD between 3 numbers is no greater than 1.
Here's the code I have so far for the method:
private int greatestCommonFactor(int a, int b, int c)
{
for(int n = 0; n <= number; n++)
{
if()
}
return 1;
}
the return 1 was already there when I started working on the lab. How can I make sure that the GCD is no more than 1? And return all three integers?
Here's the remainder of the code if it helps in figuring out what needs to be done:
import static java.lang.System.*;
public class Triples
{
private int number;
public Triples()
{
this(0);
}
public Triples(int num)
{
number = num;
}
public void setNum(int num)
{
number = num;
}
private int greatestCommonFactor(int a, int b, int c)
{
for(int n = 0; n <= number; n++)
{
if()
}
return 1;
}
public String toString()
{
String output="";
int max = number;
for(a = 1; a <= max; a++)
{
for(b = a +1; b <= max; b++)
{
for(c = b + 1; c <= max; c++)
{
if(Math.pow(a, 2)+ Math.pow(b, 2)== Math.pow(c, 2))
{
if((a%2==1 && b%2==0)|| (a%2==0 && b%2==1))
}
}
}
}
return output+"\n";
}
}
UPDATE
Here is my new coding for the same lab:
import static java.lang.System.*;
public class Triples
{
private int number;
public Triples()
{
this(0);
}
public Triples(int num)
{
number = num;
}
public void setNum(int num)
{
number = num;
}
private int greatestCommonFactor(int a, int b, int c)
{
for(int n = 0; n <= number; n++)
{
int max = number;
for(a = 1; a <= max; a++)
{
a = n;
for(b = a +1; b <= max; b++)
{
b =n;
for(c = b + 1; c <= max; c++)
{
c = n;
if(Math.pow(a, 2)+ Math.pow(b, 2)== Math.pow(c, 2))
{
if((a%2==1 && b%2==0)|| (a%2==0 && b%2==1))
{
if(a%2<=1 && b%2<=1 && c%2<=1)
{
return 1;
}
}
}
}
}
}
}
return 1;
}
public String toString()
{
String output="";
output = greatestCommonFactor(a, b, c);
return output+"\n";
}
}
You can use Euclid's algorithm to calculate the GCD of a and b. Call the result d. Then the GCD of a, b, and c is the GCD of c and d; for that, you can use Euclid's algorithm again.
Here's a brute-force way if you don't care about efficiency:
private int greatestCommonFactor(int a, int b, int c)
{
limit = Math.min(a, b);
limit = Math.min(limit, c);
for(int n = limit; n >= 2; n--)
{
if ( (a % n == 0) && (b % n == 0) && (c % n == 0) ) {
return n;
}
}
return 1;
}
Explanation:
You can save some work by only checking up to the minimum of (a, b, c). Any number greater than that definitely won't be a GCD of all 3.
You need to start your loop at n = limit instead of n = 0 and count backwards.
As soon as we come across a number that produces zero remainder for (a, b, c), that must be the GCD.
If nothing is found within the loop, GCD defaults to 1.