码迷,mamicode.com
首页 > 其他好文 > 详细

错排问题

时间:2015-07-17 18:13:51      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:

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 } 

 

错排问题

标签:

原文地址:http://www.cnblogs.com/threezj/p/4654807.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!