poj3421

简单组合数学

View Code
#include <iostream>

#include <cstdlib>

#include <cstdio>

#include <cstring>

#include <cmath>

using namespace std;



#define maxn 10005



struct Factor

{

    int value, num;

} factor[maxn];



bool is[maxn];

int prm[maxn];

int num;

int n, m;

int sum;



int getprm(int n)

{

    int i, j, k = 0;

    int s, e = (int) (sqrt(0.0 + n) + 1);



    memset(is, 1, sizeof(is));

    prm[k++] = 2;

    is[0] = is[1] = 0;

    for (i = 4; i < n; i += 2)

        is[i] = 0;

    for (i = 3; i < e; i += 2)

        if (is[i])

        {

            prm[k++] = i;

            for (s = i * 2, j = i * i; j < n; j += s)

                is[j] = 0;

        }

    for (; i < n; i += 2)

        if (is[i])

            prm[k++] = i;

    return k;

}



void dissect(int n)

{

    num = 0;

    sum = 0;

    for (int i = 0; prm[i] * prm[i] <= n && i <= m; i++)

        if (n % prm[i] == 0)

        {

            factor[num].value = i;

            factor[num].num = 0;

            while (n % prm[i] == 0)

            {

                n /= prm[i];

                factor[num].num++;

            }

            sum += factor[num].num;

            num++;

        }

    if (n > 1)

    {

        factor[num].value = n;

        factor[num++].num = 1;

        sum++;

    }

}



long long com(int n, int r)

{

    if (n - r < r)

        r = n - r;

    int i, j;

    long long s = 1;

    for (i = 0, j = 1; i < r; ++i)

    {

        s *= (n - i);

        for (; j <= r && s % j == 0; ++j)

            s /= j;

    }

//    printf("%d %d %lld\n", n, r, s);

    return s;

}



int main()

{

    //freopen("t.txt", "r", stdin);

    m = getprm(10000);

    while (~scanf("%d", &n))

    {

        dissect(n);

        long long ans = 1;

        int temp = sum;

        for (int i = 0; i < num; i++)

        {

            ans *= com(temp, factor[i].num);

            temp -= factor[i].num;

        }

        printf("%d %lld\n", sum, ans);

    }

    return 0;

}

你可能感兴趣的:(poj)