题意:开始输入两个数n和t,分别表示进入多维空间前后的飞船数,之后n个数表示n艘类别,之后两个数k和x表示n个飞船中第k个飞船,其余飞船进入多维空间后,剩余的t艘飞船中排第x位,这t艘飞船按类别从小到大排列。求的问题是剩余的t艘飞船有多少种可能组合。
题解:一开始记录比第k艘类别大于,等于,小于的飞船数gr,eq,le。在找出x位置前后的空余b,d。结果就是∑(C(eq,i)*C(le,b-i)*C(gr,d)+...+C(eq,i)*C(le,b)*C(gr,d-i))(eq>=i>=0),单纯的组合数。
代码:
#include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <vector> #include <map> #include <iostream> #include <algorithm> using namespace std; #define LL __int64 const LL maxn=5e3+5; const LL mod=1e9+7; LL a[maxn],f[maxn],g[maxn],h[maxn]; LL pow_mod(LL a,LL b,LL n)//a^b%n { LL s=1; while(b) { if(b&1) s=(s*a)%n; a=(a*a)%n; b=b>>1; } return s; } //大小比较,__int64不能直接用,哎 LL max(LL a,LL b) { return a>b?a:b; } LL min(LL a,LL b) { return a<b?a:b; } int main() { LL n,t; while(scanf("%I64d%I64d",&n,&t)!=EOF) { LL i,j,k,x,eq,gr,le,b,c,d; for(i=0;i<n;i++) scanf("%I64d",&a[i]); scanf("%I64d%I64d",&k,&x); eq=gr=le=0; //计数 for(i=0;i<n;i++) { if(a[i]==a[k-1])eq++; else if(a[i]<a[k-1])le++; else gr++; } eq--; b=x-1; d=t-x; LL ans=0; f[0]=g[0]=h[0]=1; //列举出所有C(le,0),...,C(le,le),C(eq,0),...,C(eq,eq),C(gr,0),...,C(gr,gr) for(i=1;i<=le;i++) { if(le-i<i)f[i]=f[le-i]; else f[i]=(f[i-1]*(le-i+1)%mod*pow_mod(i,mod-2,mod))%mod;//le的组合数 } for(i=1;i<=gr;i++) { if(gr-i<i)g[i]=g[gr-i]; else g[i]=(g[i-1]*(gr-i+1)%mod*pow_mod(i,mod-2,mod))%mod;//gr的组合数 } for(i=1;i<=eq;i++) { if(eq-i<i)h[i]=h[eq-i]; else h[i]=(h[i-1]*(eq-i+1)%mod*pow_mod(i,mod-2,mod))%mod;//eq的组合数 } //题解中的公式 for(i=0;i<=eq;i++) { for(j=0;j<=i;j++) { if(b-j<0)break; k=d-i+j; if(k<0)continue; ans=(ans+h[i]*f[b-j]%mod*g[k])%mod; } } printf("%I64d\n",ans); } return 0; } /* 5 3 1 3 3 3 5 3 2 */