import java.io.*; import java.util.*; import java.awt.geom.*; /** * Solution to Hill Numbers * * The trick here is to not think of the input as a number, * but rather as a sequence of digits. * * @author vanb */ public class hillnumbers_vanb { public Scanner sc; public PrintStream ps; /** * Memoization array to remember results. * It's memo[u][c][d][p] where: * u = 0 if the digits are going up, 1 if they've started going down * c = 1 if we have to constrain the digits, 0 if not * d = the previous digit * p = the position in the number, from left to right * * They're all pretty straightforward, except for constrain. * * Suppose we're wokring our way, digit by digot, through the * number 1234321. Suppose we're at the third digit, * counting hill numbers that start with 11. The nest digit is * unconstrained. We could use any digit from 0 to 9, and * still be below the input number. * * Now, suppose we're at that third digit, and we're counting * hill numbers that start with 12. We're constrained to only * use digits 0-3. Anything else, and we'll end up counting a * hill number that's larger than the input. */ public long memo[][][][] = new long[2][2][10][20]; /** We'll convert the input into an array of integer digits. */ public int digits[]; /** * Count the number of hill numbers. * * @param updn 0 if the digits are going up, 1 if they've started going down * @param constrain 1 if we have to constrain the digits, 0 if not * @param lastdigit the previous digit * @param pos the position in the number, from left to right * @return Count of hill numbers under the above conditions */ public long count( int updn, int constrain, int lastdigit, int pos ) { // At the end? Only one way to to that. if( pos==digits.length ) return 1; if( memo[updn][constrain][lastdigit][pos]<0L ) { long c=0; // Is the upp digit constrained by the input? int upper = constrain==0 ? 9 : digits[pos]; // Go through all options for digits for( int d=0; d<=upper; d++ ) { // Do we need to constrain the next level? int newconstrain = (constrain==1 && d==upper) ? 1 : 0; // If we're still going up... if( updn==0 ) { c += count( d digits[i] ) down = true; } if( ishill ) { // Initialize memo[][][][] to all -1s, // which is a flag that the value hasn't been computed yet. for( int i=0; i<10; i++ ) { Arrays.fill( memo[0][0][i], -1 ); Arrays.fill( memo[0][1][i], -1 ); Arrays.fill( memo[1][0][i], -1 ); Arrays.fill( memo[1][1][i], -1 ); } // Our count routine will include 0, which isn't positive. // So, we've got to subtract 1. ps.println( count( 0, 1, 0, 0 )-1 ); } else ps.println( -1 ); } /** * @param args */ public static void main( String[] args ) throws Exception { new hillnumbers_vanb().doit(); } }