⑨要写信

【题目描述】

某日,琪露诺写了N封信要装到N个信封里面,却全都装错了……现在想知道有多少种装错的可能性。

【输入描述】
信和信封的数量N。

【输出描述】
装错的可能性的数量。

【样例输入】
输入样例1

2

 

输入样例2

4

【样例输出】
输出样例1

1

 

输出样例2

9

【数据范围及提示】
1≤N≤100

 

简解:

源代码:

#include<cstdio>
int n,f[101];
int main()
{
    scanf("%d",&n);
    f[1]=0;
    f[2]=1;
    for (int a=3;a<=n;a++)
      f[a]=(a-1)*(f[a-1]+f[a-2]); //应用了错排公式。
    printf("%d",f[n]); //本题还应使用高精度算法,但在此忽略。
    return 0;
}

/*
数论——《错排公式》:
 
    f[n]=(n-1)*(f[n-1]+f[n-2])

  Step 1:
    把第n个元素放在任意的一个位置,例如位置k(除位置n外)。
  Step 2:
    放置第k个元素无非为以下两种可能:
    (1)放置在位置n: 
        则剩下的(n-2)个元素就有f(n-2)种放置方法。
    (2)不放置在位置n:
        则剩下的(n-2)个元素就有f(n-1)种放置方法。
*/

 

 

正解:

源代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,num[101],f[101][3001];
void x1(int t) //单精度 乘 高精度。
{
    int k(0);
    for (int a=1;a<=num[t];a++)
    {
        k+=f[t][a]*(t-1);
        f[t][a]=k%10;
        k/=10;
    }
    while (k) //挺值得学习的。
    {
        f[t][++num[t]]=k%10;
        k/=10;
    }
}
void x2(int t1,int t2) //高精度 加 高精度。
{
    int k(0);
    num[t1+1]=max(num[t1],num[t2]);
    for (int a=1;a<=num[t1+1];a++)
    {
        k+=f[t1][a]+f[t2][a];
        f[t1+1][a]=k%10;
        k/=10;
    }
    while (k)
    {
        f[t1+1][++num[t1+1]]=k%10;
        k/=10;
    }
}
int main()
{
    memset(f,0,sizeof(f));
    scanf("%d",&n);
    if (!n)
    {
        printf("0");
        return 0;
    }
    f[1][1]=0;
    f[2][1]=1;
    num[1]=num[2]=1;
    for (int a=3;a<=n;a++)
    {
        x2(a-1,a-2);
        x1(a);
    }
    for (int a=num[n];a>0;a--)
      printf("%d",f[n][a]);
    return 0;
}

 

posted @ 2016-03-26 09:43  前前前世。  阅读(147)  评论(0编辑  收藏  举报