import java.io.*; import java.util.*; import java.awt.geom.*; /** * Solution to Primal Partitions * * @author vanb */ public class primal_vanb { public Scanner sc; public PrintStream ps; /** This is an array of all of the primes <1000 */ public static int primes[] = new int[168]; /** * Generate all of the primes <1000 */ public static void generatePrimes() { boolean isprime[] = new boolean[1001]; Arrays.fill( isprime, true ); isprime[0] = false; isprime[1] = false; int index = 0; for( int i=0; i primesets[] = new TreeSet[n]; for( int i=0; i(); // OK, yes, I know: 0 isn't a prime. // But, 0 is what we need to return if there is no prime. // So, I hope you'll forgive me this indiscretion. primesets[i].add( 0 ); // Go through all of the primes <1000 and see if they're in this value for( int j=0; j1,000 in any of our values. // If we divided out all of the primes <1,000, // and there's still something left in the value, // the it must be one prime >1,000. if( value>1 ) primesets[i].add( value ); //System.err.println( i + " " + sequence[i] + " " + primesets[i] ); } // We're going to set up a simple 2D dynamic programming solution. // The question is: What's the best I can do // if i divide the first 'i' values into 'j' partition? // That's what smallest[i][j] will hold. int smallest[][] = new int[n][k+1]; // We'll need a bit more context than that, though. // We'll need to know the set of all of the primes that are // common in the previous subsequence. We'll also need to // get the largest prime of that set. TreeSet will do that for us. TreeSet sets[][] = new TreeSet[n][k+1]; // OK, let's prime the pump. // For element 0 (the first element), // it's only possible to have 1 partition. // Everything else is null or 0.. Arrays.fill( smallest[0], 0 ); Arrays.fill( sets[0], null ); // And, for 1 partition.... smallest[0][1] = primesets[0].last(); sets[0][1] = primesets[0]; // Now, go through the rest of the sequence for( int i=1; i bestset = null; int bestscore = 0; // There are two choices - either add this value to // the previous partition, or start a new partition. // This first option is adding this value // to the previous partition. if( sets[i-1][j]!=null ) { // The set of primes is the intersection of // the previous set (value i-1, j partitions), // and the set for this new value. bestset = new TreeSet(); bestset.addAll( sets[i-1][j] ); bestset.retainAll( primesets[i] ); // The best score is the biggest prime in the set. bestscore = Math.min( smallest[i-1][j], bestset.last() ); } // OK, this second option is starting a new partition. if( sets[i-1][j-1]!=null ) { // The score is the smallest of what we // had before with 1 fewer partitions (value i-i, j-1 partitions), // and the biggest prime in this new set. int score = Math.min( smallest[i-1][j-1], primesets[i].last() ); if( score > bestscore || bestset==null ) { bestscore = score; // We're starting a new partition, // so this is the set of primes in the last partitions. bestset = primesets[i]; } } //if( i>9000 && i<9100 ) System.err.println( i + " " + j + " " + sequence[i] + " " + bestscore + " " + bestset ); // Remember the best we got. smallest[i][j] = bestscore; sets[i][j] = bestset; } } // Alright, our answer is the best we can do // at the last value with k partitions. ps.println( smallest[n-1][k] ); } /** * @param args */ public static void main( String[] args ) throws Exception { new primal_vanb().doit(); } }