⑨要写信(codevs 1697)

题目描述 Description

琪露诺(冰之妖精)有操控冷气的能力。能瞬间冻结小东西,比普通的妖精更危险。一直在释放冷气的她周围总是非常寒冷。

由于以下三点原因……

  • 琪露诺的符卡 冰符“Icicle Fall”-Easy的弹幕有够蠢的,只要站在她的正前方就没任何弹幕会碰到你;
  • ZUN在《红魔乡》中介绍她时已经说她有点笨笨的了;
  • 在ZUN放出《东方花映冢》的介绍图时,在图中把琪露诺放在了⑨的位置上,并以“⑨笨蛋”简单带过,从此“⑨”及“笨蛋”就成为她的别名了……

所以琪露诺便得到了“笨蛋”的别称。

某日,琪露诺又2了……

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

输入描述 Input Description

信和信封的数量N。

输出描述 Output Description

装错的可能性的数量。

样例输入 Sample Input

输入样例1

 

2

输入样例2

 4

 

样例输出 Sample Output

输出样例1 

1

输出样例2

 9

数据范围及提示 Data Size & Hint

1≤N≤100

 

/*
  递推+高精度。第一次得了60分,把b、c数组拿到主函数外面就都过了,长记性了……
  有n封信,第i封信装错的话有i-1种可能,设i-1其中一个为k,那么k有两种装法:
    ①:装到第i个信封里,此时剩下的i-2封信要装到i-2个信封里,就有f[i-2];
    ②:装到除i之外的信封里,这时i-1的作用和i一样,剩下的就有f[i-1]; 
  综上所述,得到状态转移方程:
      f[i]=(i-1)*(f[i-1]+f[i-2])
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#define M 210
using namespace std;
struct node
{
    int a[M],len;
};node f[M];
int b[M],c[M];
int main()
{
    int n;
    scanf("%d",&n);
    f[1].a[1]=0;f[2].a[1]=1;
    f[1].len=1;f[2].len=1;
    for(int i=3;i<=n;i++)
    {
        //高精度加法 
        int lena=f[i-1].len,lenb=f[i-2].len,lenc=1,x=0;
        while(lenc<=lena||lenc<=lenb)
        {
            f[i].a[lenc]=f[i-1].a[lenc]+f[i-2].a[lenc]+x;
            x=f[i].a[lenc]/10;
            f[i].a[lenc]%=10;
            lenc++;
        }
        f[i].a[lenc]=x;
        if(f[i].a[lenc]==0)lenc--;
        f[i].len=lenc;
        //高精度乘法 
        int la=f[i].len,zh=i-1,lb=0;
        memset(b,0,sizeof(b));
        memset(c,0,sizeof(c));
        while(zh)
        {
            b[++lb]=zh%10;
            zh/=10;
        }
        for(int j=1;j<=la;j++)
        {
            int x=0;
            for(int k=1;k<=lb;k++)
            {
                c[j+k-1]+=f[i].a[j]*b[k]+x;
                x=c[j+k-1]/10;
                c[j+k-1]%=10;
            }
            c[j+lb]=x;
        }
        int lc=la+lb;
        f[i].len=lc;
        while(c[lc]==0&&lc>1)lc--;
        for(int j=lc;j>=1;j--)
          f[i].a[j]=c[j];
    }
    int flag=0;
    for(int i=f[n].len;i>=1;i--)
      if(!flag&&!f[n].a[i])continue;
      else
      {
          printf("%d",f[n].a[i]);
          flag=1;
      }
    return 0;
}
View Code

 

posted @ 2016-07-09 14:51  karles~  阅读(263)  评论(0编辑  收藏  举报