首页 > 代码库 > bjfu1238 卡特兰数取余
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#endiftypedef 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;}
bjfu1238 卡特兰数取余
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。