码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj4517[Sdoi2016]排列计数

时间:2016-08-16 23:37:26      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:

bzoj4517[Sdoi2016]排列计数

题意:

求有多少种长度为n的序列 A,满足1~n在序列中各出现了一次,且序列恰好有m个数是稳定的(若第i个数A[i]的值为i,则称i是稳定的)。共T组数据,方案数模10^9+7。T=500000,n≤1000000,m≤1000000。
题解:
显然结果为C(n,m)*f[n-m],f[n-m]为错排数满足f[i]=(f[i-1]+f[i-2])*(i-1),f[1]=0,f[0]=1。因为n,m过大,求组合数的递推法行不通,因此只能用公式:C(n,m)=n!/(m!*(n-m)!),n!先递推出来,因为最后有除法,故还须求个逆元,刚好模数是质数,所以利用费马小定理,写个快速幂就好了。
代码:
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define inc(i,j,k) for(int i=j;i<=k;i++)
 5 #define maxn 1000010
 6 #define mod 1000000007
 7 using namespace std;
 8 
 9 inline int read(){
10     char ch=getchar(); int f=1,x=0;
11     while(ch<0||ch>9){if(ch==-)f=-1; ch=getchar();}
12     while(ch>=0&&ch<=9)x=x*10+ch-0,ch=getchar();
13     return f*x;
14 }
15 long long power(int a,int b){
16     if(b==0)return 1; if(b==1)return a;
17     long long c=power(a,b>>1);
18     if(b&1)return c*c%mod*a%mod;else return c*c%mod;
19 }
20 long long a[maxn],b[maxn]; int t,n,m;
21 long long c(int n,int m){
22     return a[n]*power(a[n-m]*a[m]%mod,mod-2)%mod;
23 }
24 int main(){
25     a[0]=1; inc(i,1,maxn-10)a[i]=a[i-1]*i%mod; b[0]=1; b[1]=0; inc(i,2,maxn-10)b[i]=(b[i-1]+b[i-2])%mod*(i-1)%mod;
26     t=read();
27     while(t--){n=read(); m=read(); printf("%lld\n",c(n,m)*b[n-m]%mod);}
28     return 0;
29 }

 

20160814

bzoj4517[Sdoi2016]排列计数

标签:

原文地址:http://www.cnblogs.com/YuanZiming/p/5778103.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!