标签:
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