题目链接:点击打开链接
题意:
卡特兰数前n项和 结果%m
把答案当成2部分搞。
#include<stdio.h> #include<cmath> #define int __int64 const int N = 100000; struct inverse_element{ int x, y, q; void extend_Eulid(int a,int b) { if(b == 0){ x = 1;y = 0;q = a; }else{ extend_Eulid(b,a%b); int temp = x; x = y; y = temp - a/b*y; } } int find(int a, int b){ extend_Eulid(a, b); return x; } }inver; 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 P[N], D[N], top; void fen(int m){ top = 0; for(int i = 0; prime[i]*prime[i]<=m;i++){ if(m%prime[i])continue; D[top] = 0; P[top++] = prime[i]; while(m%prime[i] == 0) m/=prime[i]; } if(m!=1){ D[top] = 0; P[top++] = m; } } int n, m; void mul(int &x, int y){ x *= y; if(x >= m) x %= m; else if(x<0) x = x%m+m; } void work1(int &x, int u){ for(int i = 0; i < top; i++) while(u%P[i] == 0) D[i]++, u/=P[i]; mul(x, u); } void work2(int &x, int u){ for(int i = 0; i < top; i++) while(u%P[i] == 0) D[i]--, u/=P[i]; if(u!=1) mul(x, inver.find(u, 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 work(){ if(m==1)return 0; if(n==1)return 1; fen(m); int res = 1, sum = 1; for(int i = 2; i <= n; i++) { work1(res, 4*i-2); work2(res, i+1); int t = res; for(int i = 0; i < top; i++) mul(t, Pow(P[i],D[i])); sum = (sum+t)%m; } return sum; } #undef int int main() { PRIME(100000); while(~scanf("%I64d %I64d", &n, &m)){ if(n+m == 0)break; // n-=2; printf("%I64d\n", work()%m); } return 0; }
时间: 2024-12-14 18:08:31