错排问题

http://acm.hdu.edu.cn/showproblem.php?pid=1465

这道题 一开始我用全排列做 妥妥的超限

 1 #include "stdio.h"

 2 int n,count;

 3 int a[21];

 4 int equal()

 5 {

 6     int flag=1;

 7     for(int i=1;i<=n;i++)

 8     {

 9         if(a[i]==i)

10             flag=0;

11     }

12     return flag;

13 }

14 void perm(int k)

15 {

16     int temp;

17     if(k==n)

18     {

19         if(equal())

20             count++;

21     }

22     for(int i=k;i<=n;i++)

23     {

24         temp=a[i];a[i]=a[k];a[k]=temp;

25         perm(k+1);

26         temp=a[i];a[i]=a[k];a[k]=temp;

27     }

28 }

29 main()

30 {

31     while(scanf("%d",&n)!=EOF)

32     {

33     

34         for(int i=1;i<=n;i++)

35             a[i]=i;

36         perm(1);

37         printf("%d\n",count);

38         count=0;

39     }

40 } 

后来开始想递推公式

假设f(1)和f(2)可以直接口算  我们假设 前n-1和n-2 项已经排好 

当有n项时 有两种情况 

1. 前n-1项错装

2. 前n-2项错装

第一种情况

比较简单 只要把第n项与前面n-1项中任意一项交换即可  即 n-1*f(n-1)

第二种情况

那么只能是没错装的那一项与第n项交换   但是没错装的一项可以是 n-2中的任意一项  即 n-1*f(n-2)

 

因此  递推公式为  f(n)=n-1*f(n-1)+n-1*f(n-2)=(n-1)*(f(n-1)+f(n-2))

后来发现此为著名的错排公式

 1 #include "stdio.h"

 2 main()

 3 {

 4     int n; 

 5     while(scanf("%d",&n)!=EOF)

 6     {

 7         long long a[100];

 8         a[1]=0;a[2]=1;a[3]=2;    

 9         for(int i=4;i<=n;i++)

10             a[i]=(i-1)*(a[i-2]+a[i-1]);

11         printf("%I64d\n",a[n]);

12     }

13 } 

 

你可能感兴趣的:(问题)