错排序问题

题目:http://acm.hrbeu.edu.cn/index.php?act=problem&id=1008&cid=25

写的程序就那么的耗时吗?交上去都有5分钟了,还是在Waiting。费了好大劲调,也不知道对不对,留个纪念吧。

说一下思路:1,把第n 封信放在一个信封里,比如说是第 k 个 一共有 n - 1种方法

         2,放编号为 k 的信,有两种情况:

        (1)放在第 n 个信封里,那么,对剩余的 n - 2 个信,有 f (n - 2) 种方法。

        (2)不放在第 n 个信封里,这时,对于除第 n 封信以外剩余的 n - 1封信有 f ( n - 1) 种方法

所以递退公式:f ( n ) = ( n - 1) * ( f ( n - 1 )  + f ( n - 2 ) ); 其中 f (1 ) = 0, f ( 2 ) = 1 ;

其实就是一个递推题目,但是由于n最大为 1000,所以用打整数来做的

View Code
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <math.h>
 6 #define _clr(a,val) (memset(a,val,sizeof(a)))
 7 #define Max(a,b) (a) > (b) ? a : b
 8 #define Min(a,b) (a) > (b) ? b : a
 9 
10 using namespace std;
11 
12 int f[1005][7000];  //  保存 n 封信时的错位方法数,f [n][0]用来记录n封信时,错位方法数的长度
13 int tem[4];
14 int kemp[7000];
15 void ca()
16 {
17     int i,j,k;
18     _clr(f,0);
19     f[1][0] = f[2][0] = 1;
20     f[1][1] = 0;
21     f[2][1] = 1;
22     int len;
23     for(i = 3; i <= 1000; i++)
24     {
25         len = Max(f[i - 1][0],f[i - 2][0]);
26         for(j = 1; j <= len; j++)
27         {
28             f[i][j] += (f[i - 1][j] + f[i - 2][j]);  // 首先计算  f ( n - 1)  + f ( n - 2)
29             if(f[i][j] > 9)
30             {
31                 f[i][j + 1] += (f[i][j] / 10);
32                 f[i][j] %= 10;
33             }
34         }
35         if(f[i][len + 1]) f[i][0] = len + 1;
36         else f[i][0] = len;
37         int kem = i - 1;
38         int num = 0;
39         while(kem)
40         {
41             tem[++num] = kem % 10;
42             kem /= 10;
43         }
44         _clr(kemp,0);
45         for(j = 1; j <= num; j++)
46         {
47             for(k = 1; k <= f[i][0]; k++)
48             {
49                 kemp[j + k - 1] += (f[i][k] * tem[j]);  // 乘以 ( n - 1)
50                 if(kemp[j + k - 1] > 9)
51                 {
52                     kemp[j + k] += kemp[j + k - 1] / 10;
53                     kemp[j + k - 1] %= 10;
54                 }
55             }
56         }
57         if(kemp[num + f[i][0]]) f[i][0] = (num + f[i][0]);
58         else f[i][0] = (num + f[i][0] - 1);
59         for(j = 1; j <= f[i][0]; j++)
60         {
61             f[i][j] = kemp[j];
62         }
63     }
64 }
65 int main()
66 {
67     int i;
68     memset(f,0,sizeof(f));
69     ca();
70     int n;
71     //freopen("data.txt","r",stdin);
72     //freopen("data.out","w",stdout);
73     while(cin>>n)
74     {
75         i = f[n][0];
76         //cout<<f[n][0];
77         if(f[n][i] < 0) i--;
78         for(; i >= 1; i--)
79         printf("%d",f[n][i]);
80         cout<<endl;
81     }
82     return 0;
83 }
posted @ 2012-09-12 21:41  AC_Girl  阅读(241)  评论(0编辑  收藏  举报