Pagini recente » Cod sursa (job #577106) | Cod sursa (job #201523) | Cod sursa (job #1464892) | Monitorul de evaluare | Cod sursa (job #3339062)
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <climits>
#include <unordered_set>
using namespace std;
ifstream fin("pascal.in");
ofstream fout("pascal.out");
const int MAXN = 5000002;
int N, D, ans, digit_size;
unordered_set<int> invalid_numbers;
int digits[30];
void back(int lv, int value, int prime) {
if (lv == -1) {
invalid_numbers.insert(value);
return;
}
for (int i = 0; i <= digits[lv]; ++i) {
back(lv - 1, value * prime + i, prime);
}
}
void compute(int prime, int generate_negatives) {
int x = N;
ans = 1;
digit_size = 0;
while (x) {
digits[digit_size] = x % prime;
ans = ans * (1 + digits[digit_size]);
++digit_size;
x /= prime;
}
if (digit_size == 0) ++digit_size;
if (generate_negatives) {
back(digit_size - 1, 0, prime);
}
}
int main() {
fin >> N >> D;
if (D == 2 || D == 3 || D == 5) {
// Lucas theorem. Comb(N, i) is divisible by a prime p, iff at least one digit in the prime-base representation of N is smaller than the equivalent in i.
// Therefore, the only numbers that aren't divisible by p, are the ones that have smaller or equal digits in prime-base.
// Solution: Simply generate all numbers that have smaller digits and put them into a set.
compute(D, false);
fout << N + 1 - ans;
return 0;
}
if (D == 4) {
for (int i = 0; i <= N; ++i) {
// Kummer's theorem. The largest K such that p^k divides Comb(N, i) = number of carries when adding i and N-i.
// The number of carries when adding two numbers in base 2 is equivalent to counting number of 1s in the (x + y) ^ (x ^ y) representation.
// (x + y) = correct sum
// (x ^ y) = binary addition without carries
// xor-ing these shows us where the carries actually are located.
int carries = N ^ i ^ (N - i);
// We only care that there are at least 2.
if (carries > (carries & (-carries))) {
++ans;
}
}
fout << ans;
return 0;
}
if (D == 6) {
// Same as D = 2,3,5 case, just that we invalidate all numbers that either are not divisible by 2 or by 3.
// Possible optimization is to check whether you would be generating too many numbers and instead generate the correct ones. Too much work though.
compute(2, true);
compute(3, true);
fout << N + 1 - invalid_numbers.size();
return 0;
}
return 0;
}