传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2048
全错=全不匹配
设当前全错的个数是dp[n]
那么前(n-1)个全错的话,第n个数就可以从前(n-1)个任意挑选一个进行交换,得到的即是全错的;
dp[n] += (n-1)*dp[n-1]
也可以从下面这种情况样获得全错的排列:
在前(n-1)个中挑出(n-2)个全错,仅有一个对的情况,第n个数只需要和这个对的交换就能得到全错的结果。
可供挑选的(n-2)个全错的情况,在(n-1)个数中,有(n-1)种;(n-2)个全错又有dp[n-2]种
所以:
dp[n] += (n-1)*dp[n-2]
最终递推式就是:
dp[i]=(i-1)*(dp[i-1]+dp[i-2]);
#include <cstdio> #include <cstring> #include <queue> using namespace std; #define sc scanf #define pt printf #define maxe 25600 #define maxv 55 #define maxn 21 #define mll unsigned long long const int inf =2000000000; mll dp[maxn]; mll w1[maxn],w2[maxn],b1[maxn],b2[maxn]; mll A[maxn]; int main() { freopen("in.txt","r",stdin); mll i; A[1]=1; for(i=2;i<=20;++i) A[i]=A[i-1]*i; dp[2]=1,dp[3]=2; for(i=3;i<=20;++i) dp[i]=(i-1)*(dp[i-1]+dp[i-2]); int T,n; sc("%d",&T); while(T--) { sc("%d",&n); double ans = 1.0*dp[n]/A[n]; ans*=100000.0; int res = (int)ans; if(res%10>=5) res=res-res%10+10; else res=res-res%10; res/=10; //pt("%d ",res); i=4; char s[5]; while(res!=0) { s[i]=res%10+'0'; res/=10; --i; } for(++i;i<=4;++i) { if(i==3) putchar('.'); putchar(s[i]); } putchar('%'); putchar(' '); } return 0; }