Saturday, June 29, 2013

UVa 213 - Message Decoding

Accepted date: 2013-06-29
Ranking (as of 2013-06-29): 35 out of 870
Language: C++

/*
  UVa 213 - Message Decoding

  To build using Visucal Studio 2010:
    cl -EHsc UVa_213_Message_Decoding.cpp
*/

#include <cstdio>

int read_digits(int n)
{
  int d = 0, c;
  while (n--) {
    d <<= 1;
    while ((c = getchar()) == '\n')
      ;
    d += c - '0';
  }
  return d;
}

int main()
{
  char chars_map[1 + 3 + 7 + 15 + 31 + 63 + 127];
  const int chars_map_indices[] = {-1, 0, 1, 4, 11, 26, 57, 120};
    // chars_map_indices[i] is the index to chars_map[] for the key length of i
  const int terminaters[] = {0, 1, 3, 7, 15, 31, 63, 127};
    // terminaters[i] is the terminater for the key length of i
  while (true) {
    int c = getchar();
    if (c == EOF)
      break;
    else if (c == '\n')
      continue;
    // read a header
    char* p = chars_map;
    do
      *p++ = static_cast<char>(c);
    while ((c = getchar()) != '\n');
    int length;
    while (length = read_digits(3)) {
      char* q = &chars_map[chars_map_indices[length]];
      int i, t = terminaters[length];
      while ((i = read_digits(length)) != t)
        putchar(*(q + i));
    }
    putchar('\n');
  }
  return 0;
}

UVa 10364 - Square

Accepted date: 2013-06-29
Ranking (as of 2013-06-29): 139 out of 949
Language: C++

Applied backtrack.


/*
  UVa 10364 - Square

  To build using Visual Studio 2010:
    cl -EHsc -O2 UVa_10364_Square.cpp
*/

#include <iostream>
#include <algorithm>
using namespace std;

const int ns_max = 20;
struct stick {
  bool used_;
  int length_;
  bool operator<(const stick& s) const {return length_ > s.length_;}
} sticks[ns_max];

bool form_square(int n /* number of sticks */, int i /* index to sticks[] */,
  int nrs /* number of remaining sides */,
  int sl /* side length */, int rsl /* remaining side length */)
{
  if (!rsl) {
    if (!--nrs)
      return true;
    else
      return form_square(n, 0, nrs, sl, sl);
  }
  else {
    for (int j = i; j < n; j++)
      if (sticks[j].length_ <= rsl && !sticks[j].used_) {
        sticks[j].used_ = true;
        if (form_square(n, j + 1, nrs, sl, rsl - sticks[j].length_))
          return true;
        sticks[j].used_ = false;
      }
    return false;
  }
}

int main()
{
  int t;
  cin >> t;
  while (t--) {
    int n;
    cin >> n;
    int s = 0;
    for (int i = 0; i < n; i++) {
      sticks[i].used_ = false;
      cin >> sticks[i].length_;
      s += sticks[i].length_;
    }
    int sl = s / 4;
    bool yes = true;
    if (sl * 4 != s)
      yes = false;
    else {
      for (int i = 0; i < n; i++)
        if (sticks[i].length_ > sl) {
          yes = false; break;
        }
      if (yes) {
        sort(sticks, sticks + n); // sort in descending order of lengths
        yes = form_square(n, 0, 4, sl, sl);
      }
    }
    cout << ((yes) ? "yes\n" : "no\n");
  }
  return 0;
}

Saturday, June 15, 2013

UVa 571 - Jugs

Accepted date: 2011-12-20
Ranking (as of 2013-06-15): 670 out of 1520
Language: C++

/*
  UVa 571 - Jugs

  To build using Visual Studio 2008:
    cl -EHsc -O2 jugs.cpp
*/

#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std;

enum {fill_A, fill_B, empty_A, empty_B, pour_A_B, pour_B_A};

struct jugs {
  int a_, b_;
  stack<char> steps_;

  jugs(int a, int b, char s) : a_(a), b_(b) {steps_.push(s);}
  jugs(int a, int b, char s, const stack<char>& steps) : a_(a), b_(b),
    steps_(steps) {steps_.push(s);}
};

void print_steps(stack<char>& steps)
{
  const char* instructions[] = {"fill A\n", "fill B\n",
    "empty A\n", "empty B\n", "pour A B\n", "pour B A\n"};
  if (!steps.empty()) {
    char s = steps.top(); steps.pop();
    print_steps(steps);
    cout << instructions[s];
  }
}

bool push_jugs_state(int a, int b, char s, const stack<char>& steps,
  vector< vector<bool> >& states, queue<jugs>& q)
{
  if (!states[a][b]) {
    states[a][b] = true;
    q.push(jugs(a, b, s, steps));
    return true;
  }
  else
    return false;
      // do not transfer to the state that has already been transferred before
}

void pour_jugs(int ca, int cb, int n)
{
  vector< vector<bool> > states(ca + 1, vector<bool>(cb + 1, false));
    // states[i][j] is true if the state where the content of A is i and 
    // the content of B is j has already been examined
  queue<jugs> q;
  if (ca > n) {
    states[ca][0] = true;
    q.push(jugs(ca, 0, fill_A));
  }
  else {
    states[0][cb] = true;
    q.push(jugs(0, cb, fill_B));
  }
  for ( ; !q.empty(); q.pop()) {
    jugs& j = q.front();
    if (j.b_ == n) {
      print_steps(j.steps_);
      break;
    }
    int a, b, p;
    // if either of the jugs is empty, try pouring to the empty jug, 
    // or fill the empty jug
    if (!j.a_) {
      p = min(ca, j.b_);
      push_jugs_state(p, j.b_ - p, pour_B_A, j.steps_, states, q);
      if (j.b_ < cb)
        push_jugs_state(ca, j.b_, fill_A, j.steps_, states, q);
    }
    else if (!j.b_) {
      p = min(j.a_, cb);
      push_jugs_state(j.a_ - p, p, pour_A_B, j.steps_, states, q);
      if (j.a_ < ca)
        push_jugs_state(j.a_, cb, fill_B, j.steps_, states, q);
    }
    // if both of the jugs are not empty, try pouring between jags, 
    // or empty the fully-filled jug
    else {
      if (j.a_ < ca) {
        p = min(ca - j.a_, j.b_);
        push_jugs_state(j.a_ + p, j.b_ - p, pour_B_A, j.steps_, states, q);
      }
      else if (j.a_ == ca)
        push_jugs_state(0, j.b_, empty_A, j.steps_, states, q);
      if (j.b_ < cb) {
        p = min(cb - j.b_, j.a_);
        push_jugs_state(j.a_ - p, j.b_ + p, pour_A_B, j.steps_, states, q);
      }
      else if (cb == j.b_)
        push_jugs_state(j.a_, 0, empty_B, j.steps_, states, q);
    }
  }
  cout << "success\n";
}

int main()
{
  int ca, cb, n;
  while (cin >> ca >> cb >> n)
    pour_jugs(ca, cb, n);
  return 0;
}

Uva 11029 - Leading and Trailing

Accepted date: 2011-12-24
Ranking (as of 2013-06-15): 242 out of 513
Language: C++

/*
  Uva 11029 - Leading and Trailing

  To build using Visual Studio 2008:
    cl -EHsc -O2 leading_and_trailing.cpp
*/

#include <iostream>
#include <iomanip>
#include <cmath>
#ifdef __ELAPSED_TIME__
#include <ctime>
#endif
using namespace std;

int leading(int n, int k)
{
/*
  n^k = 10^(k * logn)
  decimal part of n^k = 10^(decimal part of k * log(n))
*/
  double k_log_n = static_cast<double>(k) * log10(static_cast<double>(n));
  double decimal_part_of_k_log_n = k_log_n - floor(k_log_n);
  double decimal_part = pow(10.0, decimal_part_of_k_log_n);
  return static_cast<int>(decimal_part * 100.0);
}

long long trailing(int n, int k)
{
  if (!k)
    return 1;
  long long t = trailing(n, k / 2);
  t = (t * t) % 1000;
  if (k & 1) // k is odd
    t = (t * n) % 1000;
  return t;
}

int main()
{
  int nr_cases;
  cin >> nr_cases;
#ifdef __ELAPSED_TIME__
  clock_t start = clock();
#endif
  while (nr_cases--) {
    int n, k;
    cin >> n >> k;
    cout << leading(n, k) << "..." <<
      setfill('0') << setw(3) << trailing(n, k) << endl;
  }
#ifdef __ELAPSED_TIME__
  cerr << "elapsed time = " <<
    static_cast<double>(clock() - start) / CLOCKS_PER_SEC << " sec.\n";
#endif
  return 0;
}

Uva 10023 - Square root

Accepted date: 2011-12-25
Ranking (as of 2013-06-15): 408 out of 875
Language: JAVA

// Uva 10023 - Square root

/*
  See Methods of computing square roots - Wikipedia, the free encyclopedia.
    (http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Digit-by-digit_calculation)
*/

import java.util.Scanner;
import java.math.BigInteger;

class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    String line = sc.nextLine();
    int nr_cases = Integer.parseInt(line);
    while (nr_cases-- > 0) {
      sc.nextLine(); // skip a line
      line = sc.nextLine();
      System.out.println(squareRoot(line.trim()));
      if (nr_cases > 0)
        System.out.println();
    }
  }

  static String squareRoot(String n) {
    final BigInteger TWENTY = BigInteger.TEN.add(BigInteger.TEN);
    int i = 0;
    BigInteger c = BigInteger.valueOf(n.charAt(i++) - '0'); // current value
    if ((n.length() & 1) == 0)
      c =
        c.multiply(BigInteger.TEN).add(BigInteger.valueOf(n.charAt(i++) - '0'));
    BigInteger p = BigInteger.ZERO; // part of the root found so far
    while (true) {
      // determine the greatest digit x such that y = (20 * p + x) * x 
      // does not exceed c
      BigInteger x = BigInteger.ZERO, y = BigInteger.ZERO;
      if (p.equals(BigInteger.ZERO)) {
        if (!c.equals(BigInteger.ZERO)) {
          x = BigInteger.valueOf((long)Math.sqrt(c.doubleValue()));
            // x = floor(sqrt(c))
          y = x.multiply(x); // y = x * x
        }
      }
      else {
        BigInteger twenty_p = p.multiply(TWENTY);
        x = c.divide(twenty_p); // c / (20 * p)
        y = twenty_p.add(x).multiply(x); // (20 * p + x) * x
        int result = y.compareTo(c);
        if (result < 0) {
          for (x = x.add(BigInteger.ONE); ; x = x.add(BigInteger.ONE)) {
            y = twenty_p.add(x).multiply(x);
            if (y.compareTo(c) > 0)
              break;
          }
          x = x.subtract(BigInteger.ONE);
          y = twenty_p.add(x).multiply(x);
        }
        else if (result > 0) {
          for (x = x.subtract(BigInteger.ONE);
            ; x = x.subtract(BigInteger.ONE)) {
            y = twenty_p.add(x).multiply(x);
            if (y.compareTo(c) <= 0)
              break;
          }
        }
      }
      c = c.subtract(y);
      p = p.multiply(BigInteger.TEN).add(x);
//      System.out.println(String.format("%s %s", p, c));
      if (i == n.length())
        break;
      c =
        c.multiply(BigInteger.TEN).add(BigInteger.valueOf(n.charAt(i++) - '0'));
      c =
        c.multiply(BigInteger.TEN).add(BigInteger.valueOf(n.charAt(i++) - '0'));
    }
    return p.toString();
  }
}

UVa 10308 - Roads in the North

Accepted date: 2011-12-28
Ranking (as of 2013-06-15): 211 out of 742
Language: C++

/*
  UVa 10308 - Roads in the North

  To build using Visual Studio 2008:
    cl -EHsc -O2 roads_in_the_north.cpp
*/

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <utility>
#include <algorithm>
using namespace std;

const int nr_villages_max = 10000;

vector< vector< pair<int, int> > > roads(nr_villages_max + 1);
  // roads[i].first is the number of village adjacent to the village i
  // roads[i].second is the length of road between the village i and 
  // roads[i].first

int dfs(int v, int pv, int& diameter)
{
  int max_d = 0, second_max_d = 0;
  for (vector< pair<int, int> >::const_iterator i = roads[v].begin(),
    e = roads[v].end(); i != e; ++i) {
    if (i->first == pv)
      continue;
    int d = i->second + dfs(i->first, v, diameter);
    if (d > max_d) {
      second_max_d = max_d; max_d = d;
    }
    else if (d > second_max_d)
      second_max_d = d;
  }
  diameter = max(diameter, max_d + second_max_d);
  return max_d;
}

int main()
{
  int nr_villages = 0;
  string line;
  do {
    getline(cin, line);
    if (!cin.eof() && !line.empty()) {
      istringstream iss(line);
      int vi, vj, l;
      iss >> vi >> vj >> l;
      if (vi > nr_villages || vj > nr_villages) {
        int i = max(vi, vj);
        for (int j = nr_villages + 1; j <= i; j++)
          roads[j].clear();
        nr_villages = i;
      }
      roads[vi].push_back(make_pair(vj, l));
      roads[vj].push_back(make_pair(vi, l));
    }
    else if (nr_villages) { // end of a set of input
      int diameter = 0;
      // calculate the diameter (or longest path) of a tree, 
      // using depth-first search
      dfs(1, 0, diameter);
      cout << diameter << endl;
      nr_villages = 0;
    }
    else if (!cin.eof()) // no input lines
      cout << 0 << endl;
  } while (!cin.eof());
  return 0;
}

UVa 10375 - Choose and divide

Accepted date: 2012-01-02
Ranking (as of 2013-06-15): 141 out of 976
Language: C++

/*
  UVa 10375 - Choose and divide

  To build using Visual Studio 2008:
    cl -EHsc -O2 choose_and_divide.cpp
*/

#include <iostream>
#include <utility>
#include <algorithm>
#include <limits>
#include <cstdio>
using namespace std;

/*
  C(p, q) / C(r, s) = (p! * s! * (r - s)!) / (q! * r! * (p - q)!)
*/

const int nr_facts = 3; // number of factorials

bool multiply_by_partial_factorial(pair<int, int>& pfact, double result_max,
  double& result)
{
  int i;
  for (i = pfact.first; i <= pfact.second; ) {
    result *= static_cast<double>(i++);
    if (result > result_max)
      break;
  }
  pfact.first = i;
  return pfact.first > pfact.second;
}

bool divide_by_partial_factorial(pair<int, int>& pfact, double result_min,
  double& result)
{
  int i;
  for (i = pfact.first; i <= pfact.second; ) {
    result /= static_cast<double>(i++);
    if (result < result_min)
      break;
  }
  pfact.first = i;
  return pfact.first > pfact.second;
}

int main()
{
  int p, q, r, s;
  while (cin >> p >> q >> r >> s) {
    int dvd_facts[nr_facts] = {p, s, r - s}, // dividend factorials
      dvs_facts[nr_facts] = {q, r, p - q}; // divisor factorials
    sort(dvd_facts, dvd_facts + nr_facts);
    sort(dvs_facts, dvs_facts + nr_facts);
    int i, j, nr_dvd_pfacts = 0, nr_dvs_pfacts = 0;
    pair<int, int> dvd_pfacts[nr_facts], dvs_pfacts[nr_facts];
      // dividend/divisor partial factorials
    for (i = 0; i < nr_facts; i++) {
      if (dvd_facts[i] > dvs_facts[i])
        dvd_pfacts[nr_dvd_pfacts++] = make_pair(dvs_facts[i] + 1, dvd_facts[i]);
      else if (dvd_facts[i] < dvs_facts[i])
        dvs_pfacts[nr_dvs_pfacts++] = make_pair(dvd_facts[i] + 1, dvs_facts[i]);
    }
    i = j = 0;
    double result = 1.0;
    const double result_min =
      numeric_limits<float>::min(), result_max = numeric_limits<float>::max();
    do {
      if (i < nr_dvd_pfacts &&
        multiply_by_partial_factorial(dvd_pfacts[i], result_max, result))
        i++;
      if (j < nr_dvs_pfacts &&
        divide_by_partial_factorial(dvs_pfacts[j], result_min, result))
        j++;
    } while (i < nr_dvd_pfacts || j < nr_dvs_pfacts);
    printf("%.5lf\n", result);
  }
  return 0;
}