きったんの頭

/*
 * pe15.c
 * https://mind.kittttttan.info/c/pe15
 */

/* https://mind.kittttttan.info/c/divs */
#include "divs.h"

#include <stdio.h>
#include <stdint.h>

#ifdef _WIN32
#define UINT64 "I64u"
#else
#define UINT64 "llu"
#endif

typedef struct _DivsData {
  int len;
  unsigned long divs[32];
} DivsData;

/*
 *  (m + n)! / (m! * n!)
 */
void pe15(int m, int n) {
  static const int MAX_M = 64;
  static const int MAX_N = 64;

  int ps[MAX_M];
  DivsData dd[MAX_N];
  int i, j, k;
  uint64_t a;

  if (m > MAX_M || n > MAX_N) {
    printf("Too Large: max numbers are (%d, %d).\n", MAX_M, MAX_N);
    return;
  }
  if (m < n) {
    i = m; m = n; n = i;
  }

  for (i = 0; i < m; i++) {
    ps[i] = i + n + 1;
  }

  for (i = 0; i < n - 1; i++) {
    dd[i].len = get_divs(dd[i].divs, (unsigned long)i + 2);
  }

  for (i = 0; i < m; ++i) {
    for (j = 0; j < n - 1; ++j) {
      for (k = 0; k < dd[j].len; ++k) {
        if (dd[j].divs[k] > 1 && ps[i] % dd[j].divs[k] == 0) {
          ps[i] /= dd[j].divs[k];
          dd[j].divs[k] = 0;
          if (ps[i] < 2) {
            goto nextps;
          }
        }
      }
    }
nextps:
; // dummy to avoid compile error
  }

  a = 1;
  for (i = 0; i < m; i++) {
    if (ps[i] > 1) {
      a *= ps[i];
    }
  }

  printf("(%d + %d)! / (%d! * %d!) = %" UINT64 "\n",
          m, n, m, n, a);
}

int main() {
  int m, n;

  puts("Probrem 15:");
  while (1) {
    if (scanf("%d %d", &m, &n) != 2) {
      scanf("%*s");
      puts("Input Number.");
    } else {
      if (!m && !n) {
        break;
      }
      pe15(m, n);
    }
  }

  return 0;
}