人群中钻出个光头
TimeLimit:1000MS MemoryLimit:256MB
64-bit integer IO format:%lld
Problem Description
Input
有多组样例,每组样例一行,包含两个整数 n, Mn, M,用空格隔开。
Output
每组样例输出一行,所求抽法数对 $10^9+7$ 取余后的值。
SampleInput
3 1 233 233
SampleOutput
4 734436443
题意的话见人话部分就好了。。。。。,这题其实就是求一个组合数,从m钟物品中取n个物品,就是多重集合排列问题(x1+x2+...+xm=n),用m-1个隔板把n个物品分隔开就好,即C(n+m-1,n),
由于m是从0-m,有m+1种,那么ans=C(n+m,n);
多重排列问题:
线性方程 x1 + x2 + ... + xk = r 一共有多少组非负整数解?
解答:上述不定方程的非负整数解对应于下述排列
1...101...1 01...1 0 ...... 01...1
x1 个 x2 个 x3 个 ...... xk 个
其中 k-1个 0 将 r 个 1 分成k段, 每段含1的个数分别为 x1, x2, ..., xk,
很明显这个排列是多重集合 S = { r * 1, (k-1)* 0 }的全排列
即:P(r+k-1; r*1, (k-1)*0) = (r+k-1)! / ( r! * (k-1)! ) = C( r+k-1, r),即从k类元素中选r个的种类;
这一题,求组合数的话,要提前预处理2e6的阶乘以及逆元,不然会超时;
1 #include<stdio.h> 2 #define ll long long 3 const ll mod=1e9+7; 4 const ll maxn=2e6+7; 5 ll quick_pow(ll a,ll b) 6 { 7 ll ans=1; 8 while(b) 9 { 10 if(b&1) 11 ans=ans*a%mod; 12 b>>=1; 13 a=a*a%mod; 14 } 15 return ans; 16 } 17 ll fac[maxn+7],inv[maxn+7];///fac阶乘,inv阶乘的逆元也就是倒数 18 void init() 19 { 20 fac[0]=fac[1]=1; 21 for(int i=2;i<=maxn;i++) 22 fac[i]=i*fac[i-1]%mod; 23 24 inv[maxn]=quick_pow(fac[maxn],mod-2); 25 for(int i=maxn-1;i>=0;i--) 26 inv[i]=inv[i+1]*(i+1)%mod; 27 28 return ; 29 } 30 ll C(ll n,ll m) 31 { 32 return fac[n]%mod*(inv[m]%mod*inv[n-m]%mod)%mod%mod; 33 } 34 int main() 35 { 36 init(); 37 ll n,m; 38 while(~scanf("%lld",&n)) 39 { 40 printf("%lld ",fac[n]); 41 } 42 return 0; 43 }