uva 10139 factovisors

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 = b
The 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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章