3 3 1 3 2 4 2
0.3333 0.6667 0.6250HintSample Explanation When N = 3, there are 6 possible distributions of keys: Room 1 Room 2 Room 3 Destroy Times #1 Key 1 Key 2 Key 3 Impossible #2 Key 1 Key 3 Key 2 Impossible #3 Key 2 Key 1 Key 3 Two #4 Key 3 Key 2 Key 1 Two #5 Key 2 Key 3 Key 1 One #6 Key 3 Key 1 Key 2 One In the first two distributions, because Key 1 is locked in Room 1 itself and you can’t destroy Room 1, it is impossible to open Room 1. In the third and forth distributions, you have to destroy Room 2 and 3 both. In the last two distributions, you only need to destroy one of Room 2 or Room
递推关系的说明:
考虑第p个物品,p可以单独构成一个非空循环排列,这样前p-1种物品构成k-1个非空循环排列,方法数为s(p-1,k-1);
也可以前p-1种物品构成k个非空循环排列,而第p个物品插入第i个物品的左边,这有(p-1)*s(p-1,k)种方法。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=20; long long f[25],stir[25][25]; int solve() { int i,j; f[0]=1; for(i=1;i<=maxn;i++) f[i]=i*f[i-1]; //因为N有N!种排列顺序,这作为总数 //计算概率 for(i=1;i<=maxn;i++) stir[i][0]=0; stir[1][1]=1; for(i=1;i<=maxn;i++) for(j=1;j<=i;j++) { if(i==j) stir[i][j]=1; else stir[i][j]=stir[i-1][j-1]+(i-1)*stir[i-1][j]; } for(i=1;i<=maxn;i++) for(j=1;j<=maxn;j++) if(stir[i][j]<0) stir[i][j]=-stir[i][j]; return 0; } int main() { int cas,n,i,k; long long sum; solve(); scanf("%d",&cas); while(cas--) { scanf("%d %d",&n,&k); sum=0; for(i=1;i<=k;i++) sum+=stir[n][i]-stir[n-1][i-1]; printf("%.4lf\n",1.0*sum/f[n]); //因为写成printf("%.4lf\n",(double)sum/f[n]); //run time error! 下次一定记好了! } return 0; }
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #define oo 0x13131313 using namespace std; long long H[21]; long long F[21][21]; long long T[21]; long long C[21][21]; void CLT(int n,int len) { long long tot=n; long long k=1; for(int i=1;i<=len;i++) { if(T[i]==1) { k*=C[tot-1][1]; tot-=T[i]; } else { k*=(C[tot][T[i]]*H[T[i]-1]); tot-=T[i]; } } tot=1; T[len+1]=0; for(int i=2;i<=len+1;i++) { if(T[i]==T[i-1]) { tot++; } else { k=k/H[tot]; tot=1; } } F[n][len]+=k; } int getxulie(int n,long long tot,int prev,int len,int deep) { T[deep]=prev; tot+=prev; if(deep==len) if(tot==n) { CLT(n,len); return 1; } else return 0; for(int i=prev;i<=n-len+1;i++) getxulie(n,tot,i,len,deep+1); return 0; } void YCLYCL() { H[0]=1; for(int i=1;i<=20;i++) { H[i]=H[i-1]*i; } for(int i=1;i<=20;i++) C[i][0]=1; C[1][1]=1; for(int i=2;i<=20;i++) for(int j=1;j<=i;j++) { C[i][j]=C[i-1][j-1]+C[i-1][j]; } } void YCL() { YCLYCL(); for(int i=2;i<=20;i++) for(int j=1;j<=i;j++) { for(int k=1;k<=i-j+1;k++) { memset(T,0,sizeof(T)); getxulie(i,0,k,j,1); } } for(int i=2;i<=20;i++) for(int j=1;j<=i;j++) { F[i][j]+=F[i][j-1]; } } void inin() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); } int main() { //inin(); YCL(); int K; cin>>K; int a;int b; while(K--) { cin>>a>>b; printf("%.4lf\n",((double)F[a][b]/(double)H[a])); } }