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;
}
原文地址:https://www.cnblogs.com/rainydays/p/2755131.html