# bzoj2111 Perm 排列计数

Input

Output

Sample Input

20 23

Sample Output

16

Hint

100%的数据中，1 ≤ � N ≤ 106, P� ≤ 10^9，p是一个质数。 数据有所加强

 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\n",f[1]);
53 }

posted @ 2017-09-24 20:45  Kaiser-  阅读(99)  评论(0编辑  收藏  举报