bjfu1238 卡特兰数取余
题目就是指定n,求卡特兰数Ca(n)%m。求卡特兰数有递推公式、通项公式和近似公式三种,因为要取余,所以近似公式直接无法使用,递推公式我简单试了一下,TLE。所以只能从通项公式入手。
Ca(n) = (2*n)! / n! / (n+1)!
思想就是把Ca(n)质因数分解,然后用快速幂取余算最后的答案。不过,算n!时如果从1到n依次质因数分解,肯定是要超时的,好在阶乘取余有规律,不断除素因子即可。
最后还是擦边过,可能筛法写得一般吧,也算是题目要求太柯刻。
/* * Author : ben */ #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <iostream> #include <algorithm> #include <queue> #include <set> #include <map> #include <stack> #include <string> #include <vector> #include <deque> #include <list> #include <functional> #include <numeric> #include <cctype> using namespace std; #ifdef ON_LOCAL_DEBUG #else #endif typedef long long LL; const int MAXN = 80000; const int N = 1000001; bool isPrime[N + 3];//多用两个元素以免判断边界 int pn, pt[MAXN], num[MAXN]; void init_prime_table() { memset(isPrime, true, sizeof(isPrime)); int p = 2, q, del; double temp; while (p <= N) { while (!isPrime[p]) { p++; } if (p > N) {//已经结束 break; } temp = (double) p; temp *= p; if (temp > N) break; while (temp <= N) { del = (int) temp; isPrime[del] = false; temp *= p; } q = p + 1; while (q < N) { while (!isPrime[q]) { q++; } if (q >= N) { break;} temp = (double) p; temp *= q; if (temp > N) break; while (temp <= N) { del = (int) temp; isPrime[del] = false; temp *= p; } q++; } p++; } pn = 0; for (int i = 2; i <= N; i++) { if (isPrime[i]) { pt[pn++] = i; } } } int modular_exp(int a, int b, int c) { LL res, temp; res = 1 % c, temp = a % c; while (b) { if (b & 1) { res = res * temp % c; } temp = temp * temp % c; b >>= 1; } return (int) res; } void getNums(int n) { int x = 2 * n; int len = pn; for (int i = 0; i < len && pt[i] <= x; i++) { int r = 0, a = x; while (a) { r += a / pt[i]; a /= pt[i]; } num[i] = r; } x = n; for (int i = 0; i < len && pt[i] <= x; i++) { int r = 0, a = x; while (a) { r += a / pt[i]; a /= pt[i]; } num[i] -= r; } x = n + 1; for (int i = 0; i < len && pt[i] <= x; i++) { int r = 0, a = x; while (a) { r += a / pt[i]; a /= pt[i]; } num[i] -= r; } } int main() { #ifdef ON_LOCAL_DEBUG freopen("data.in", "r", stdin); // freopen("test.in", "r", stdin); // freopen("data.out", "w", stdout); #endif int n, m; init_prime_table(); while (scanf("%d%d", &n, &m) == 2) { getNums(n); LL ans = 1; int n2 = 2 * n; for (int i = 0; ans && (i < pn) && pt[i] <= n2; i++) { if (num[i] > 0) { ans = ans * (LL) modular_exp(pt[i], num[i], m); ans %= m; } } printf("%d\n", (int)ans); } return 0; }