Cod sursa(job #3339040)

Utilizator parus_majorParus Major parus_major Data 5 februarie 2026 21:32:44
Problema Pascal Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.84 kb
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <climits>

using namespace std;

ifstream fin("pascal.in");
ofstream fout("pascal.out");

const int MAXN = 5000002;

int N, D, ans;
int fact[MAXN], fact2[MAXN];

static inline void compute_fact(int prime, int fact[]) {
    for (int i = prime; i <= N; i *= prime) {
        for (int j = i; j <= N; j += i) {
            fact[j]++;
        }
    }
    for (int i = 1; i <= N; ++i) fact[i] += fact[i - 1];
}

int main() {
    fin >> N >> D;

    if (D == 2 || D == 3 || D == 5) {
        compute_fact(D, fact);

        for (int i = 0; i <= N; ++i) {
            const int cnt = fact[N] - fact[N - i] - fact[i];
            if (cnt) ++ans;
        }
        fout << ans;
        return 0;
    }

    if (D == 4) {
        //compute_fact(2, fact);

        //int ans2 = 0;
        for (int i = 0; i <= N; ++i) {
            //const int cnt = fact[N] - fact[N - i] - fact[i];
            //if (cnt > 1) {
            //    ++ans2;
            //}

            // Kummer's theorem. The largest K such that p^k divides Comb(N, i) = number of carries when adding i and N-i
            // Check if there are at least 2 carries. These come from matching bits of 1 in (i) and (N - i).
            // Cases:
            // 1) There are no matching bits between i and N-i -> Comb(N, i) is not divisible by even 2
            // 2) There are more than one matching bits of 1 between i and N-i -> Comb(N, i) is at least divisible by 2^2
            // 3) There is exactly one matching bit of 1 between i and N-i. In order for Comb(N,i) to be divisible by 2^2, you need that carry to produce another carry.
            const int matching_bits = i & (N - i);
            // Case 1)
            if (matching_bits == 0) continue;
                        
            const int last_matching_bit = matching_bits & (-matching_bits);
            // Case 2)
            if (last_matching_bit != matching_bits) {
                ++ans;
                continue;
            }

            // Compute the remaining addition without the carry. It needs to be odd so that the previous carry produces another carry.
            const int remaining_addition = (i / last_matching_bit) / 2 + ((N - i) / last_matching_bit) / 2;
            if ((remaining_addition & 1) == 1) {
                ++ans;
            }

        }
        fout << ans;
        return 0;
    }

    if (D == 6) {
        compute_fact(2, fact);
        compute_fact(3, fact2);

        for (int i = 0; i <= N; ++i) {
            const int cnt = fact[N] - fact[N - i] - fact[i];
            const int cnt2 = fact2[N] - fact2[N - i] - fact2[i];
            if (cnt && cnt2) {
                ++ans;
            }
        }
        fout << ans;
        return 0;
    }

    return 0;
}