题目链接:点击打开链接
首先要n-=2,然后就是一个卡特兰数了。
上一题用的是 h(n) = h(n-1) * (4n-2)/(n+1);
这题用的是 h(n) = (2n)! * n! / (n+1)!;
然后对阶乘分解质因数:
分解完了直接快速幂。
#include<stdio.h> #include<iostream> #include<cmath> #include<cstring> using namespace std; #define int __int64 const int N = 100000; int prime[N],primenum;//有primenum个素数 math.h void PRIME(int Max_Prime){ primenum=0; prime[primenum++]=2; for(int i=3;i<=Max_Prime;i+=2) for(int j=0;j<primenum;j++) if(i%prime[j]==0)break; else if(prime[j]>sqrt((double)i) || j==primenum-1) { prime[primenum++]=i; break; } } int n, m; void mul(int &x, int y){ x *= y; if(x >= m) x %= m; else if(x<0) x = x%m+m; } int Pow(int x, int y){ int ans = 1; while(y){ if(y&1) mul(ans, x); mul(x, x); y >>= 1; } return ans; } int D[N]; void work1(int x){ for(int i = 0; prime[i]<=x; i++){ D[i] = 0; for(int j = prime[i]; j <= x; j*=prime[i]) D[i] += x/j; } } void work2(int x){ for(int i = 0; prime[i]<=x; i++) for(int j = prime[i]; j <= x; j*=prime[i]) D[i] -= x/j; } void debug(){ for(int i = 0; i<primenum; i++) if(D[i])printf("[%d,%d]\n", prime[i],D[i]);puts(""); } int work(){ if(m==1)return 0; if(n==1)return 1; int res = 1; //f[n] = 2n!/n!/(n+1)!; work1(2*n); work2(n); work2(n+1); for(int i = 0; prime[i] <= 2*n; i++) if(D[i]) mul(res, Pow(prime[i],D[i])); return res; } #undef int int main() { PRIME(1000000); while(cin>>n>>m){ n-=2; cout<< work()%m <<endl; } return 0; }
时间: 2024-10-10 14:57:37