Saturday, July 13, 2013

UVa 10020 - Minimal coverage

Accepted date: 2011-11-05
Ranking (as of 2013-07-13): 620 out of 1913
Language: C++

/*
  UVa 10020 - Minimal coverage

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

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

const size_t nr_segments_max = 100000;
pair<int, int> segments[nr_segments_max + 1];
  // segments[i].first is i-th segment's left end, 
  // and segments[i].second is its right end
int chosen_segments[nr_segments_max];
  // indices of chosen segments from segments[]

bool compare_segment(const pair<int, int>& i, const pair<int, int>& j)
{
  if (i.first < j.first)
    return true;
  else if (i.first > j.first)
    return false;
  else
    return i.second > j.second;
}

int choose_segments(int m, int nr_segments)
{
  // sort the segments in ascending order of their left ends and 
  // for the ties in descending order of their right ends
  sort(segments, segments + nr_segments, compare_segment);
  // find the leftmost segment
  int si = 0, psi = -1;
  for ( ; si < nr_segments; si++) {
    if (segments[si].first > 0)
      break;
    else if (psi == -1 || segments[si].second > segments[psi].second)
      psi = si;
  }
  int ci = 0;
  chosen_segments[ci++] = psi;
  if (segments[psi].second >= m)
    return ci; // segment [0, m] is covered by only one segment
  for ( ; si < nr_segments; si++) {
    if (segments[psi].second < segments[si].first)
      // there is a segment that is not covered
      return 0;
    if (segments[psi].second >= segments[si].second)
      // segments[si] is completely covered by segments[psi]
      continue;
    if (segments[chosen_segments[ci - 1]].second < segments[si].first)
      ci++;
    chosen_segments[ci] = si;
    if (segments[si].second >= m)
      break;
    psi = si;
  }
  return ci + 1;
}

int main()
{
  int nr_cases;
  cin >> nr_cases;
  string s;
  getline(cin, s); // skip '\n'
  getline(cin, s); // skip a blank line
  while (nr_cases--) {
    getline(cin, s);
    istringstream iss(s);
    int m;
    iss >> m;
    iss.clear();
    int nr_segments = 0;
    int l_min = numeric_limits<int>::max(),
      r_max = numeric_limits<int>::min();
    while (true) {
      getline(cin, s);
      iss.str(s);
      pair<int, int> sg;
      iss >> segments[nr_segments].first >>
        segments[nr_segments].second;
      iss.clear();
      if (!segments[nr_segments].first && !segments[nr_segments].second)
        break;
      l_min = min(l_min, segments[nr_segments].first);
      r_max = max(r_max, segments[nr_segments].second);
      nr_segments++;
    }
    int nr_chosen_segments = (l_min > 0 || r_max < m) ?
      0 : choose_segments(m, nr_segments);
    cout << nr_chosen_segments << endl;
    for (int i = 0; i < nr_chosen_segments; i++)
      cout << segments[chosen_segments[i]].first << ' ' <<
        segments[chosen_segments[i]].second << endl;
    if (nr_cases) {
      cout << endl;
      getline(cin, s); // skip a line
    }
  }
  return 0;
}

UVa 10405 - Longest Common Subsequence

Accepted date: 2011-11-11
Ranking (as of 2013-07-13): 159 out of 6767
Language: C++

/*
  UVa 10405 - Longest Common Subsequence

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

#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;

const int nr_chars_max = 1024;
char first_s[nr_chars_max], second_s[nr_chars_max];
int lcs_c[2][nr_chars_max];

int lcs(int first_s_length, int second_s_length)
{
  memset(lcs_c[0], 0, sizeof(int) * (second_s_length + 1));
  memset(lcs_c[1], 0, sizeof(int) * (second_s_length + 1));
  for (int i = 1; i <= first_s_length; i++) {
    int ci = i % 2, pi = (i - 1) % 2;
    for (int j = 1; j <= second_s_length; j++) {
      if (first_s[i - 1] == second_s[j - 1])
        lcs_c[ci][j] = lcs_c[pi][j - 1] + 1;
      else
        lcs_c[ci][j] = max(lcs_c[ci][j - 1], lcs_c[pi][j]);
    }
  }
  return lcs_c[first_s_length % 2][second_s_length];
}

int main()
{
  while (gets(first_s)) {
    gets(second_s);
    printf("%d\n", lcs(strlen(first_s), strlen(second_s)));
  }
  return 0;
}

UVa 10465 - Homer Simpson

Accepted date: 2011-11-23
Ranking (as of 2013-07-13): 1685 out of 2392
Language: C++

/*
  UVa 10465 - Homer Simpson

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

#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
#ifdef __ELAPSED_TIME__
#include <ctime>
#endif
using namespace std;

pair<int, int> how_many_burgers_to_eat(int m, int n, int t)
{
  vector< pair<bool, int> > burgers(t + 1, make_pair(false, 0));
    // burgers[i].first is true if time of i is realized
    // burgers[i].second is the number of bergers Homer can eat in time of i
  burgers[0].first = true;
  int i;
  for (i = min(m, n); i <= t; i++) {
    if (i >= m && i >= n) {
      if (burgers[i - m].first && burgers[i - n].first)
        burgers[i] = make_pair(true,
          max(burgers[i - m].second + 1, burgers[i - n].second + 1));
      else if (burgers[i - m].first)
        burgers[i] = make_pair(true, burgers[i - m].second + 1);
      else if (burgers[i - n].first)
        burgers[i] = make_pair(true, burgers[i - n].second + 1);
    }
    else if (i >= m) {
      if (burgers[i - m].first)
        burgers[i] = make_pair(true, burgers[i - m].second + 1);
    }
    else {
      if (burgers[i - n].first)
        burgers[i] = make_pair(true, burgers[i - n].second + 1);
    }
  }
  for (i = t; i; i--)
    if (burgers[i].first)
      break;
  return make_pair(burgers[i].second, t - i);
}

int main()
{
#ifdef __ELAPSED_TIME__
  time_t start = clock();
#endif
  int m, n, t;
  while (cin >> m >> n >> t) {
    pair<int, int> result = how_many_burgers_to_eat(m, n, t);
    cout << result.first;
    if (result.second)
      cout << ' ' << result.second;
    cout << endl;
  }
#ifdef __ELAPSED_TIME__
  cerr << "elapsed time = " <<
    static_cast<double>(clock() - start) / CLOCKS_PER_SEC << " sec.\n";
#endif
  return 0;
}

UVa 128 - Software CRC

Accepted date: 2011-12-05
Ranking (as of 2013-07-13): 122 out of 3150
Language: C++

/*
  UVa 128 - Software CRC

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

#include <cstdio>

unsigned int calculate_crd(const char* line)
{
  unsigned int g = 34943;
  unsigned int remainder = 0;
  for ( ; *line; line++, remainder <<= 8) {
    remainder |= *line;
    remainder %= g;
  }
  remainder <<= 8;
  unsigned int crc = 0;
  if (remainder % g) {
    unsigned int quotient = remainder / g;
    crc = g * (quotient + 1) & 0xffff;
  }
  return crc;
}

int main()
{
  while (true) {
    const int nr_chrs_max = 1024;
    char line[nr_chrs_max + 1];
    gets(line);
    if (line[0] == '#')
      break;
    unsigned int crc = calculate_crd(line);
    printf("%02X %02X\n", (crc & 0xff00) >> 8, crc & 0xff);
  }
  return 0;
}

UVa 106 - Fermat vs. Pythagoras

Accepted date: 2011-12-07
Ranking (as of 2013-07-13): 97 out of 3493
Language: C++

For more information, see:
Pythagorean triple - Wikipedia, the free encyclopedia
Tree of primitive Pythagorean triples - Wikipedia, the free encyclopedia
Formulas for generating Pythagorean triples - Wikipedia, the free encyclpedia


/*
  UVa 106 - Fermat vs. Pythagoras

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

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

int calculate_pythagorean_triples(int n, int x, int y, int z,
  vector<bool>& triples)
{
  if (x > n || y > n || z > n)
    return 0;
#ifdef DEBUG
  cerr << x << ' ' << y << ' ' << z << endl;
#endif
  for (int nx = x, ny = y, nz = z; nx <= n && ny <= n && nz <= n;
    nx += x, ny += y, nz += z)
    triples[nx] = triples[ny] = triples[nz] = true;
  const int nr_triples = 3;
  const int matrices[nr_triples][nr_triples][nr_triples] = {
    {{-1, 2, 2}, {-2, 1, 2}, {-2, 2, 3}},
    {{1, 2, 2}, {2, 1, 2}, {2, 2, 3}},
    {{1, -2, 2}, {2, -1, 2}, {2, -2, 3}}
  };
  int nr_pt = 0;
  for (int i = 0; i < nr_triples; i++) {
    int cx = matrices[i][0][0] * x + matrices[i][0][1] * y +
      matrices[i][0][2] * z,
      cy = matrices[i][1][0] * x + matrices[i][1][1] * y +
        matrices[i][1][2] * z,
      cz = matrices[i][2][0] * x + matrices[i][2][1] * y +
        matrices[i][2][2] * z;
    nr_pt += calculate_pythagorean_triples(n, cx, cy, cz, triples);
  }
  return nr_pt + 1;
}

int main()
{
#ifdef __ELAPSED_TIME__
  clock_t start = clock();
#endif
  int n;
  while (cin >> n) {
    if (n < 5)
      cout << 0 << ' ' << n << endl;
    else {
      vector<bool> triples(n + 1, false);
      int nr_primitive_triples =
        calculate_pythagorean_triples(n, 3, 4, 5, triples);
      int nr_not_triples = 0;
      for (int i = 1; i <= n; i++)
        if (!triples[i])
          nr_not_triples++;
      cout << nr_primitive_triples << ' ' << nr_not_triples << endl;
    }
  }
#ifdef __ELAPSED_TIME__
  cerr << "elapsed time = " <<
    static_cast<double>(clock() - start) / CLOCKS_PER_SEC << " sec.\n";
#endif
  return 0;
}

UVa 10717 - Mint

Accepted date: 2011-12-15
Ranking (as of 2013-07-13): 186 out of 793
Language: C++

/*
  UVa 10717 - Mint

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

#include <iostream>
#include <vector>
#include <set>
#include <limits>
#include <algorithm>
#ifdef __ELAPSED_TIME__
#include <ctime>
#endif
using namespace std;

/*
  lcm(a, b) = (a * b) / gcd(a, b)
  lcm(a, b, c) = lcm(a, lcm(b, c))
  lcm(a, b, c, d) = lcm(a, lcm(b, c, d))
*/

long long calculate_gcd(long long a, long long b)
{
  if (a < b)
    return calculate_gcd(b, a);
  if (!b)
    return a;
  else
    return calculate_gcd(b, a % b);
}

long long calculate_lcm(long long a, long long b)
{
    return (a * b) / calculate_gcd(a, b);
}

void calculate_lcms(int n, const vector<int>& coins, set<long long>& lcms)
{
  // C(50, 4) = 50! / {(50 - 4)!4!} = (50 * 49 * 48 * 47) / (4 * 3 * 2 * 1) = 
  //   50 * 49 * 2 * 47 = 230,300
  for (int i = 0; i < n - 3; i++)
    for (int j = i + 1; j < n - 2; j++) {
      long long lcm_i_j = calculate_lcm(coins[i], coins[j]);
      for (int k = j + 1; k < n - 1; k++) {
        long long lcm_i_j_k = calculate_lcm(lcm_i_j, coins[k]);
        for (int l = k + 1; l < n; l++)
          lcms.insert(calculate_lcm(lcm_i_j_k, coins[l]));
      }
    }
}

int main()
{
#ifdef __ELAPSED_TIME__
  clock_t start = clock();
#endif
  while (true) {
    int n, t;
    cin >> n >> t;
    if (!n && !t)
      break;
    vector<int> coins(n), tables(t);
    for (int i = 0; i < n; i++)
      cin >> coins[i];
    for (int i = 0; i < t; i++)
      cin >> tables[i];
    set<long long> lcms;
    calculate_lcms(n, coins, lcms);
    for (int i = 0; i < t; i++) {
      int table = tables[i];
      long long not_exceeding = numeric_limits<long long>::min(),
        not_less_than = numeric_limits<long long>::max();
      for (set<long long>::const_iterator j = lcms.begin(), e = lcms.end();
        j != e; ++j) {
        long long lcm = *j;
        long long ne = (table / lcm) * lcm;
        if (ne == table) {
          not_exceeding = not_less_than = table;
          break;
        }
        else {
          not_exceeding = max(not_exceeding, ne);
          not_less_than = min(not_less_than, ne + lcm);
        }
      }
      cout << not_exceeding << ' ' << not_less_than << endl;
    }
  }
#ifdef __ELAPSED_TIME__
  cerr << "elapsed time = " <<
    static_cast<double>(clock() - start) / CLOCKS_PER_SEC << " sec.\n";
#endif
  return 0;
}

Thursday, July 11, 2013

UVa 737 - Gleaming the Cubes

Accepted date: 2013-07-11
Ranking (as of 2013-07-11): 177 out of 860
Language: C++

/*
  UVa 737 - Gleaming the Cubes

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

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

bool get_overlapped_range(const pair<int, int>& i, const pair<int, int>& j,
  pair<int, int>& k)
{
  k.first = max(i.first, j.first);
  k.second = min(i.second, j.second);
  return (k.first < k.second) ? true : false;
}

int main()
{
  while (true) {
    int n;
    cin >> n;
    if (!n)
      break;
    int d;
    pair<int, int> px, py, pz, cx, cy, cz, nx, ny, nz;
    cin >> px.first >> py.first >> pz.first >> d;
    px.second = px.first + d;
    py.second = py.first + d;
    pz.second = pz.first + d;
    bool intersection = true;
    while (--n) {
      cin >> cx.first >> cy.first >> cz.first >> d;
      if (intersection) {
        cx.second = cx.first + d;
        cy.second = cy.first + d;
        cz.second = cz.first + d;
        if (get_overlapped_range(px, cx, nx) &&
          get_overlapped_range(py, cy, ny) && get_overlapped_range(pz, cz, nz)) {
          px = nx; py = ny; pz = nz;
        }
        else
          intersection = false;
      }
    }
    if (intersection)
      cout << (px.second - px.first) *
        (py.second - py.first) * (pz.second - pz.first) << endl;
    else
      cout << 0 << endl;
  }
  return 0;
}