题目链接:点击打开链接
题意:
卡特兰数前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;
}