/* Use the Java I/O routines */ import java.io.*; /** * See BIO exam paper. This program solves BIO'97 question 3 part a. * * Solution copyright (c) 1998 The British Informatics Olympiad (BIO). * * This program may be freely copied by persons or organisations * involved in the British Informatics Olympiad or the International * Olympiad in Informatics, on condition that no changes are made and * this notice is not altered. Distribution for profit is forbidden * unless permission is first obtained in writing from the BIO. * * This program is for educational purposes only and comes with no * warranty, implied or otherwise, as to its fitness for any purpose. * * Author: Antony Rix * Internet: http://www.christs.cam.ac.uk/bio/ * E-mail: a.rix@lineone.net * S-mail: The British Informatics Olympiad * Christ's College * Cambridge CB2 3BU * United Kingdom */ class BIO97Q3A extends AppletConsoleApp { /** * Parameters A and B */ int A = 1, B = 2; /** * Start the application from the command line. */ public static void main(String[] args) { BIO97Q3A thisApp = new BIO97Q3A(); thisApp.redirectStreams(System.in, System.out); thisApp.run(); } /** * Main program of BIO97Q3A, this is run from the command line * by the main() method, or called directly by an * AppletConsole. * * The program reads from the stream in and writes * to the stream out, which are automatically assigned * by main() or by the AppletConsole class. */ public void run() { out.println("BIO'97 Q3a:"); out.println("Enter a/b, 0"); try { /* Create a StreamTokenizer to allow us to read in the two numbers */ StreamTokenizer sin = new StreamTokenizer( in ); sin.nextToken(); A = (int)sin.nval; sin.nextToken(); B = (int)sin.nval; } catch (IOException e) { out.println("I/O failure"); }; if( (A == 0) && (B == 0) ) { A = 1; B = 20; process(); A = 36; B = 612; process(); A = 2; B = 15; process(); A = 2; B = 37; process(); A = 27; B = 441; process(); A = 4; B = 109; process(); A = 59; B = 211; process(); A = 101; B = 103; process(); A = 907; B = 911; process(); A = 523; B = 547; process(); } else { if( (A < 1) || (B <= A) || (B > 1000) ) out.println("Requires 0= 1. */ void process() { int D, BD, AD; int[] C = new int[4]; int[] N = new int[4]; int Sum; int BDBest = 1; int BDMax; int[] CBest = new int[4]; int Kmax = 4; int DenMax = 32001; boolean Solved = false; int[] Divisors = new int[1000]; int nDivisors; int i, j, k; out.println( A + "/" + B ); if( B > 100 ) BDMax = 32000; else BDMax = A * B * B; D = 1; BD = B; AD = A; while( (!Solved) || (BD <= BDMax) ) { // generate divisors nDivisors = 0; i = 1; while( (i <= AD) && (nDivisors < 1000) ) { if( (BD % i) == 0 ) { Divisors[nDivisors] = i; nDivisors++; } i++; } // generate permutations of divisors k = 1; N[0] = 0; C[0] = Divisors[N[0]]; Sum = C[0]; while( N[0] < nDivisors ) { if( Sum == AD ) { // solution found if( (k < Kmax) || ((k == Kmax) && ((BD / C[0]) < DenMax)) ) { Solved = true; Kmax = k; BDBest = BD; DenMax = BD / C[0]; out.print( "Best solution so far: " ); for( j = k-1; j >= 0; j-- ) { out.print( BD / C[j] + " " ); CBest[j] = C[j]; } out.println(); } } if( (Sum >= AD) || (N[k-1] >= (nDivisors-1)) ) { // backtrack if( k > 1 ) { Sum -= (C[k-1] + C[k-2]); k--; N[k-1]++; C[k-1] = Divisors[N[k-1]]; Sum += C[k-1]; } else N[0] = nDivisors; } if( Sum < AD ) { // add another number to the set if( (k < Kmax) && (N[k-1] < (nDivisors-1)) ) { N[k] = N[k-1] + 1; C[k] = Divisors[N[k]]; Sum += C[k]; k++; } else { Sum -= C[k-1]; N[k-1]++; C[k-1] = Divisors[N[k-1]]; Sum += C[k-1]; } } } // try next value of D D++; BD = B * D; AD = A * D; } if( Solved ) { out.print( A + "/" + B + " = 1/" + BDBest / CBest[Kmax-1]); for( j = Kmax-2; j >= 0; j-- ) out.print( " + 1/" + BDBest / CBest[j] ); out.println(); } else out.println( "No solution found!" ); } /** * Returns lowest common factor using Euclid's algorithm. * Requires a < b. */ int greatestCommonDivisor(int a, int b) { if (a == 0) return b; else return greatestCommonDivisor(b % a, a); } }