首先考虑dp,设f[i,j]表示1~i用过了,期中j个放在偶数位然后转移大家都会
这显然TLE,我们观察这个dp,任意前i个数,无论怎么放,放在奇数位的数的个数一定要大于等于放在偶数位的个数
于是很明显这是经典的卡特兰数模型
注意这里涉及到了除法取模,而模数不一定是质数
很显然的想法是分解质因数然后约分
但有更漂亮的做法,http://blog.csdn.net/jasonzhu8/article/details/5949622
1 var v,b,p:array[0..2000010] of longint; 2 n,i,j,mo,t:longint; 3 ans:int64; 4 5 procedure calc(x,w:longint); 6 begin 7 while v[x]<>0 do 8 begin 9 inc(b[v[x]],w); 10 x:=x div v[x]; 11 end; 12 inc(b[x],w); 13 end; 14 15 function quick(x:int64;y:longint):int64; 16 begin 17 quick:=1; 18 while y>0 do 19 begin 20 if y mod 2=1 then quick:=quick*x mod mo; 21 y:=y div 2; 22 x:=x*x mod mo; 23 end; 24 end; 25 26 begin 27 readln(n,mo); 28 for i:=2 to 2*n do 29 begin 30 if v[i]=0 then 31 begin 32 inc(t); 33 p[t]:=i; 34 end; 35 for j:=1 to t do 36 begin 37 if int64(i)*int64(p[j])>2*n then break; 38 v[i*p[j]]:=p[j]; 39 if i mod p[j]=0 then break; 40 end; 41 end; 42 for i:=n+2 to 2*n do 43 calc(i,1); 44 for i:=2 to n do 45 calc(i,-1); 46 ans:=1; 47 for i:=1 to t do 48 ans:=ans*quick(p[i],b[p[i]]) mod mo; 49 writeln(ans); 50 end.