JZYZOJ1544 [haoi2016T2]放棋子 错排公式 组合数学 高精度

http://172.20.6.3/Problem_Show.asp?ID=1544&a=ProbNF

看了题解才意识到原题有错排的性质(开始根本不知道错排是什么)。

十本不同的书放在书架上。现重新摆放,使每本书都不在原来放的位置。有几种摆法?
这个问题的解答就是10个元素的错排数。

错排定义:考虑一个有n个元素的排列,若一个排列中所有的元素都不在自己原来的位置上,那么这样的排列就称为原排列的一个错排。

错排数的递推式
当n个编号元素放在n个编号位置,元素编号与位置编号各不对应的方法数(错排数)用D(n)表示,
那么D(n) = (n-1) *[D(n-2) + D(n-1)];

还是数学方面的积累太少了

代码

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<iostream>
 6 using namespace std;
 7 const int maxn=210;
 8 struct har{
 9     int e[maxn*3],len;
10     har(){memset(e,0,sizeof(e));len=1;}
11 };har f[maxn];
12 int n;
13 har plu(har x,har y){
14     har z;z.len=max(x.len,y.len);
15     for(int i=1;i<=z.len;i++){
16         z.e[i]+=x.e[i]+y.e[i];
17         z.e[i+1]+=z.e[i]/10;
18         z.e[i]%=10;
19         if(z.e[i+1]>0&&z.len<i+1){
20             z.len=i+1;
21         }
22     }
23     return z;
24 }
25 har mul(har x,int k){
26     har z;z.len=x.len;
27     for(int i=1;i<=z.len;i++){
28         z.e[i]+=x.e[i]*k;
29         z.e[i+1]+=z.e[i]/10;
30         z.e[i]%=10;
31         if(z.e[i+1]>0&&z.len<i+1){
32             z.len=i+1;
33         }
34     }
35     return z;
36 }
37 void put(har x){
38     for(int i=x.len;i>=1;i--){
39         printf("%d",x.e[i]);
40     }cout<<endl;
41 }
42 int main(){
43     scanf("%d",&n);int x;
44     for(int i=1;i<=n;i++){
45         for(int j=1;j<=n;j++){
46             scanf("%d",&x);
47         }
48     }
49     f[2].e[1]=1;
50     f[1].e[1]=0;
51     for(int i=3;i<=n;i++){
52         f[i]=mul(plu(f[i-1],f[i-2]),i-1);
53     }
54     put(f[n]);
55     return 0;
56 }
View Code

原文地址:https://www.cnblogs.com/137shoebills/p/7788240.html