Problem D: Factovisors
The factorial function, n! is defined thus for n a non-negative integer:0! = 1 n! = n * (n-1)! (n > 0)We say that a divides b if there exists an integer k such that
k*a = bThe input to your program consists of several lines, each containing two non-negative integers, n and m, both less than 2^31. For each input line, output a line stating whether or not m divides n!, in the format shown below.
Sample Input
6 9 6 27 20 10000 20 100000 1000 1009
Output for Sample Input
9 divides 6! 27 does not divide 6! 10000 divides 20! 100000 does not divide 20! 1009 does not divide 1000!
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <list>
#include <set>
using std::set;
using std::list;
struct Factor {
int fac;
int pow;
Factor(): fac(0), pow(0) {}
Factor(int f, int p): fac(f), pow(p) {}
};
const int PRIME_SZ_MAX = 32 * 32 * 64;
int prime[PRIME_SZ_MAX];
int primeSz;
bool isPrime[PRIME_SZ_MAX];
void GeneratePrimes() {
memset (isPrime, 1, sizeof (isPrime));
for (int i=2; i<PRIME_SZ_MAX; ++i) {
for (int k=i+i; isPrime[i] && k<PRIME_SZ_MAX; k+=i) {
isPrime[k] = false;
}
}
primeSz = 0;
for (int i=2; i<PRIME_SZ_MAX; ++i) {
if (isPrime[i]) {
prime[primeSz++] = i;
}
}
}
void GetFactors (int n, list <Factor> &factor) {
factor.clear();
int i = 0;
int p = 0;
while (n > 1) {
if (n % prime[i] == 0) {
n /= prime[i];
++p;
} else if (i + 1 < primeSz) {
if (p) {
factor.push_front (Factor (prime[i], p));
}
p = 0;
++i;
} else {
assert (i + 1 >= primeSz);
factor.push_front (Factor (n, p = 1));
n = 1;
p = 0;
}
}
if (p) {
factor.push_front (Factor (prime[i], p));
p = 0;
}
}
bool IsDivisable (int fac, int n) {
list <Factor> factor;
GetFactors (n, factor);
set <int> toSkip;
for (list <Factor>::iterator it = factor.begin(); it != factor.end(); ++it) {
bool toMarkSkip = (it->pow == 1 && it->fac <= fac && toSkip.find(it->fac) == toSkip.end());
if (toMarkSkip) {
toSkip.insert (it->fac);
it = factor.erase (it);
--it;
}
}
while (fac && !factor.empty()) {
int f = fac;
if (factor.front().fac > f) {
break;
}
if (toSkip.find(f) != toSkip.end()) {
--fac;
continue;
}
for (list <Factor>::iterator it = factor.begin(); it != factor.end(); ++it) {
while (f > 1) {
if (f % it->fac == 0) {
f /= it->fac;
--(it->pow);
} else {
break;
}
if (it->pow == 0) {
it = factor.erase (it);
--it;
break;
}
}
bool toMarkSkip = (it != factor.end() && it->pow == 1 && it->fac < fac && toSkip.find (it->fac) == toSkip.end());
if (toMarkSkip) {
toSkip.insert (it->fac);
it = factor.erase (it);
--it;
}
}
--fac;
}
return factor.empty();
}
int main (int argc, char **argv) {
GeneratePrimes();
int n, m;
while (scanf ("%d%d", &n, &m) == 2) {
printf ("%d %s %d!\n", m, IsDivisable (n, m) ? "divides" : "does not divide", n);
}
return 0;
}