题目描述 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
思路:
经典错排问题,f[n]=(n-1)*(f[n-1]+f[n-2])
高精+递推
题解:
#include<iostream>
#include<cstdio>
using namespace std;
int a[350];//a记录第n项;
int b[350];//b记录第n-2项;
int c[350];//c记录第n-1项
int d[350]; //d记录乘法
int f[4]={0,0,1,2};
void add()
{
for(int i=1;i<=350;i++)
{
a[i]+=b[i];
a[i+1]+=a[i]/10;
a[i]%=10;
}
}
void multi(int x)
{
for(int i=1;i<=350;i++)
{
a[i]=a[i]*x;
d[i+1]+=a[i]/10;
a[i]%=10;
}
}
int main()
{
int n;
scanf("%d",&n);
if(n<=3)
{
printf("%d",f[n]);
}
else
{
a[1]=2,b[1]=1;
for(int i=4;i<=n;i++)
{
for(int j=1;j<=350;j++)
{
c[j]=a[j];
}
add();
for(int j=1;j<=350;j++)
{
b[j]=c[j];
}
multi(i-1);
for(int j=1;j<=350;j++)
{
a[j]+=d[j];
a[j+1]+=a[j]/10;
a[j]%=10;
d[j]=0;
}
}
int l=350;
while(a[l]==0&&l>1)
{
l--;
}
for(int i=l;i>=1;i--)
{
printf("%d",a[i]);
}
}
return 0;
}