题目传送:衡阳八中http://61.187.179.132:8080/JudgeOnline/showproblem?problem_id=1485
[HNOI2009]有趣的数列
Time Limit:10000MS Memory Limit:65536K
Total Submit:56 Accepted:31
Case Time Limit:1000MS
Description
我们称一个长度为2n的数列是有趣的。当且仅当该数列潲足以下三个条件:
(1)它是从1到2n共2n个整数的一个排列{ai}:
(2)所有的奇数项满足a1(3)任意相邻的两项a(2i-1)与a(2i),(1≤i≤n)满足奇数项小于偶数项,即a(2i-1)与a(2i)。
现在的任务是一对于给定的n,请求出有多少个不同的长度为2n的有趣的数列。因为最后
的答案可能很大,所以只要求输出答案mod P的值。
Input
读入数据.输入文件只包含用空格隔开的两个整数n和p.输入数据保证.
50%的数据满足n<=1000,100%的数据满足n<=l000000且p≤1000000000。
Output
包含一个整数.表示不同的长度为2n的有趣的数列个数mod p的值。
Sample Input
3 10
Sample Output
5
Hint
对应的5个有趣的数列分别为(1,2,3,4,5,6),(1,2,3,5,4,6),(1,3,2,4,5,6),(1,3,2,5,4,6),(1,4,2,5,3,6))。
卡特兰数第n项:C(n,2*n)/(n+1)
var f,a:array[1..1000000] of longint; n,p,i:longint;ans,tp:int64; s:array[1..25] of longint; //两种快速幂 function pow(k,tot:int64):int64; begin if tot=0 then exit(1); pow:=sqr(pow(k,tot>>1)); if odd(tot) then pow:=pow*k; pow:=pow mod p; end; {function pow(k,tot:longint):int64; var c,i:longint;tmp:int64; begin fillchar(s,sizeof(s),0); c:=0;tmp:=tot; pow:=1; while tmp<>0 do begin inc(c);s[c]:=tmp and 1;tmp:=tmp>>1; end; tmp:=k mod p; for i:=1 to c do begin if s[i]=1 then pow:=pow*tmp mod p; tmp:=tmp*tmp mod p; end; end; } begin readln(n,p); fillchar(f,sizeof(f),0); for i:=2 to 2*n do if f[i]=0 then begin tp:=int64(i)*int64(i); while tp<=(n<<1) do begin f[tp]:=i;tp:=tp+i; end; end; ans:=1; for i:=2 to n do a[i]:=-1; for i:=n+2 to 2*n do a[i]:=1; for i:=2*n downto 2 do if f[i]<>0 then begin inc(a[f[i]],a[i]); inc(a[i div f[i]],a[i]); end else ans:=ans*pow(i,a[i]) mod p; writeln(ans); end.