Timus[1055. Combinations]

原题地址: Timus[1055. Combinations]

类似于求n!尾部有多少个零,基于Legendre theorem。

#include <iostream>

using namespace std;

const int MAX_N = 50000;

const int MAX_PRIMES = 5133;

int N, M;

int K;

int primes[MAX_PRIMES];

int A[MAX_PRIMES];

int tag[((MAX_N - 1) / 2 + 31) >> 5];

bool test(int x)
{
    return (tag[x >> 5] & (1 << (x & 0x1F))) != 0;
}

void set(int x)
{
    tag[x >> 5] |= 1 << (x & 0x1F);
}

void input()
{
    cin >> N >> M;
}

void initialize()
{
    for (int i = 0; ((i << 1) + 3) * ((i << 1) + 3) <= N; ++i)
    {
        if (!test(i))
        {
            for (int k = 2 * i * i + 6 * i + 3; (k << 1) + 2 < N; k += 2 * i + 3)
            {
                set(k);
            }
        }
    }

    K = 0;
    primes[K++] = 2;
    for (int i = 0; (i << 1) + 2 < N; ++i)
    {
        if (!test(i))
        {
            primes[K++] = 2 * i + 3;
        }
    }
}

void process(int x, bool add)
{
    for (int i = 0; i < K && primes[i] <= x; ++i)
    {
        int z = primes[i];
        int y = x;
        while (y >= z)
        {
            if (add)
            {
                A[i] += y / z;
            }
            else
            {
                A[i] -= y / z;
            }
            y /= z;
        }
    }
}

int solve()
{
    initialize();
    if (2 * M > N)
    {
        M = N - M;
    }
    process(N, true);
    process(M, false);
    process(N - M, false);
    int ans = 0;
    for (int i = 0; i < K; ++i)
        ans += A[i] != 0;
    return ans;
}

int main()
{
    input();
    cout << solve() << endl;
    return 0;
}

 

posted @ 2018-11-13 17:17  knull  Views(146)  Comments(0)    收藏  举报