Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* package codechef; // don't place package name! */
- import java.util.*;
- import java.lang.*;
- import java.io.*;
- class ProductMath{
- public static final int DEFAULT_RADIX = 1000000000;
- public static int[] breakToInt(long x){// breaks a long into
- // at most two ints.
- // n.b. constant space...
- // because Integer.MAX_VALUE**2 < Long.MAX_VALUE
- int[] digits = new int[2];
- digits[0] = (int)(x % Integer.MAX_VALUE);
- long tempCarry = x - digits[0];
- digits[1] = (int)(tempCarry / Integer.MAX_VALUE);
- return digits;
- }
- public static int countDigits(long x, int radix){
- // counts the number of digits (of size [radix])
- int logRatio = (int)(Math.log(x)/Math.log(radix));
- return logRatio + 1;
- // if x has more than Integer.MAX_VALUE digits
- // you're gonna have a bad time
- }
- public static int[] breakToRadix(long x, int radix){
- // breaks a long into digits between [0, radix]
- int nDigits = countDigits(x, radix);
- // upper nDigits is an upper bound
- ArrayList<Integer> digits = new ArrayList<Integer>(nDigits);
- long carrier = x;// modified trial division.
- int curDigit;
- for(int i = 0; i < nDigits; i++){
- // the following operations are mathematically guaranteed:
- curDigit = (int)(carrier % radix);
- // will fit in an int if radix < INT_MAX
- digits.add(curDigit);
- // curDigit will assuredly be less than radix
- carrier -= curDigit;
- // if b = (a+b)%c, then a is divisible by c
- if(carrier <= 0){ break; }
- carrier /= radix;
- }
- int[] result = new int[digits.size()];
- for(int i = 0; i < digits.size(); i++){
- result[i] = digits.get(i).intValue();
- // unbox int (ArrayList requires object boxing)
- }
- return result;
- }
- }
- class BigProduct{
- public int radix;// so far my code only works radix=10**n
- private ArrayList<Integer> digits;
- public boolean mutable = true;
- public BigProduct(){
- this.radix = ProductMath.DEFAULT_RADIX;
- this.digits = new ArrayList<Integer>();
- this.setValue(0);
- }
- public BigProduct(int radix){
- this.radix = radix;
- this.digits = new ArrayList<Integer>();
- this.setValue(0);
- }
- public BigProduct(BigProduct toClone){
- this.radix = toClone.radix;
- this.digits = new ArrayList<Integer>();
- this.setValue(toClone);
- }
- public boolean setValue(long x){
- if(this.mutable){
- this.digits.clear();
- this.consumeAdd(x);
- return true;
- }else{ return false; }
- }
- public void setValue(BigProduct x){
- if(this.mutable){
- this.radix = x.radix;
- this.digits = new ArrayList<Integer>(x.digits);
- }
- }
- public boolean consumeAdd(long x, int power){
- if(this.mutable){
- int i = power;
- int j = this.digits.size();
- // first unused index i.e. if the power is somehow very large
- while(j < i){// make room for x * (radix ** power)
- this.digits.add(0);
- j++;
- }
- long result = x;
- int cdigit;
- while(true){
- if(i+1 > this.digits.size()){
- this.digits.add(0);
- }
- result += this.digits.get(i);
- cdigit = (int)(result % (long)this.radix);
- this.digits.set(i, cdigit);
- result -= cdigit;
- if(result == 0){break;}
- result /= radix;
- i += 1;
- }
- return true;
- }else{ return false; }
- }
- public boolean consumeAdd(BigProduct x){
- if(this.mutable){
- for(int i = 0; i < x.digits.size(); i++){
- this.consumeAdd(x.digits.get(i), i);
- }
- return true;
- }else{ return false; }
- }
- public boolean consumeAdd(long x){
- return this.consumeAdd(x, 0);
- }
- public void consumeMultiply(int x){
- // only needs to work for 0 <= n <= 100 for codechef
- long[] newDigits = new long[this.digits.size()];
- for(int i = 0; i < this.digits.size(); i++){
- newDigits[i] = (long)this.digits.get(i) * x;
- }
- this.digits.clear();
- for(int i = 0; i < newDigits.length; i++){
- this.consumeAdd(newDigits[i], i);
- }
- }
- public String toString(){
- // only works when radix is a power of ten
- StringBuilder result = new StringBuilder();
- int i = this.digits.size() - 1;
- result.append(this.digits.get(i--));
- String current;
- while(i >= 0){
- current = String.format("%09d", this.digits.get(i--));
- result.append(current);
- }
- return result.toString();
- }
- }
- class Factorializer{
- public static ArrayList<BigProduct> memotable;
- static int ntoi(int n){
- return (n <= 0)?1:n;
- }
- public static void initialize(){
- memotable = new ArrayList<BigProduct>();
- BigProduct temp = new BigProduct();
- temp.consumeAdd(1);
- memotable.add(temp);
- temp = new BigProduct();
- temp.consumeAdd(1);
- memotable.add(temp);
- }
- static{
- initialize();
- }
- public static BigProduct factorialize(int n){
- // only concerned about the first 100 factorials
- int i = ntoi(n);
- if(i < memotable.size()){
- return memotable.get(i);
- }
- BigProduct result = new BigProduct(
- factorialize(n-1));
- result.consumeMultiply(n);
- memotable.add(result);
- return result;
- }
- public static void clearMemos(){// only useful as debug or gc
- memotable.clear();
- initialize();
- }
- }
- class Main {
- static final String sep = "\n\t";
- static final int nTests = 100;
- static final Scanner x = new Scanner(System.in);
- static long randLong(long start, long end){
- //bounds checking must be manual
- double baser = Math.random();
- long range = end - start;
- return Math.round(baser * range) + start;
- }
- static void testCase(int n){
- BigProduct y = Factorializer.factorialize(n);
- System.out.printf("\t" + "[n] calculate n! => %d!" +
- sep + "[y] BigProduct: %s\n", n, y.toString());
- }
- static long time(){
- return System.nanoTime();
- }
- public static void interactiveTests(){
- long start, end;
- int n;
- String input;
- x.useDelimiter("\n");
- ArrayList<Long> startTimes = new ArrayList<Long>();
- ArrayList<Long> endTimes = new ArrayList<Long>();
- int i = 0;
- while(true){
- i++;
- input = x.next();
- if(input.equals("clear")){
- System.out.println("Clearing memo table");
- Factorializer.clearMemos();
- continue;
- }
- try{
- n = Integer.parseInt(input);
- }catch(NumberFormatException e){
- break;
- }
- System.out.printf("Test case %d:\n", i, nTests);
- start = time();
- testCase(n);
- end = time();
- System.out.printf("\tResult calculated in %d ns\n", end-start);
- startTimes.add(start);
- endTimes.add(end);
- }
- }
- public static void codechefLogic(){
- int n = x.nextInt();
- for(int i = 0; i < n; i++){
- System.out.println(
- Factorializer.factorialize(x.nextInt()).toString());
- }
- }
- public static void main(String[] args) {
- interactiveTests();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement