称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案可能很大,只能输出模P以后的值
Input
输入文件的第一行包含两个整数 n和p,含义如上所述。
Output
输出文件中仅包含一个整数,表示计算1,2,⋯, �的排列中, Magic排列的个数模 p的值。
Sample Input
20 23
Sample Output
16
Hint
100%的数据中,1 ≤ � N ≤ 106, P� ≤ 10^9,p是一个质数。 数据有所加强
题解:题目意思比较好理解,就是问你有多少种小根堆,那么根可以确定,然后左边右边就是
组合一下,确定,如果只有一个点,那么方案数就为1,size为1,不然就是左右子树合并。
这样瞎搞。。。(⊙o⊙)…,就好了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #define N 1000007 7 #define M 1007 8 #define ll long long 9 using namespace std; 10 11 int n,p; 12 ll fac[N],ni[N],f[N]; 13 int siz[N]; 14 15 ll C(int n,int m) 16 { 17 if(m>n) return 0; 18 if(n<p) return fac[n]*ni[m]%p*ni[n-m]%p; 19 return C(n/p,m/p)*C(n%p,m%p)%p; 20 } 21 int main() 22 { 23 int i; 24 scanf("%d%d",&n,&p); 25 fac[0]=ni[0]=ni[1]=1; 26 27 for(i=1;i<=n&&i<p;i++) 28 fac[i]=fac[i-1]*i%p; 29 for(i=2;i<=n&&i<p;i++) 30 ni[i]=(p-p/i)*ni[p%i]%p; 31 32 for(i=2;i<=n&&i<p;i++) 33 (ni[i]*=ni[i-1])%=p; 34 for(i=n;i>=1;i--) 35 { 36 if(i*2+1<=n) 37 { 38 siz[i]=1+siz[i*2]+siz[i*2+1]; 39 f[i]=f[i*2]*f[i*2+1]%p*C(siz[i]-1,siz[i*2])%p; 40 } 41 else if(i*2<=n) 42 { 43 f[i]=f[i*2]; 44 siz[i]=1+siz[i*2]; 45 } 46 else 47 { 48 f[i]=1; 49 siz[i]=1; 50 } 51 } 52 printf("%lld ",f[1]); 53 }