话说天下大势,分久必合,合久必分。。。却道那魏蜀吴三国鼎力之时,多少英雄豪杰以热血谱写那千古之绝唱。古人诚不我欺,确是应了那句“一将功成万骨枯”。
是夜,明月高悬。诸葛丞相轻摇羽扇,一脸愁苦。原来是日前蜀国战事吃紧,丞相彻夜未眠,奋笔急书,于每个烽火台写下安排书信。可想,这战事多变,丞相运筹 帷幄,给诸多烽火台定下不同计策,却也实属不易。
谁成想这送信小厮竟投靠曹操,给诸葛丞相暗中使坏。这小厮将每封书信都投错了烽火台,居然没有一封是对的。不多时小厮便被抓住,前后之事却也明朗。这可急坏了诸葛丞相,这书信传错,势必会让蜀军自乱阵脚,不攻自破啊! 诸葛丞相现在想知道被这小厮一乱,这书信传错共有多少种情况。
题目有多组数据,处理到文件结尾,丞相共写了n(1 <= n <= 20)封书信,输入一个正数n。
输出书信传错的情况数。
Sample Input
1
3
6
Sample Output
0
2
265
引自张老师PPT(万分感谢)
找规律:
对n封信以及n个信封各自按照从 1…….n 进行编号。
f[n]-----n个编号的信放在n个编号的信封,各不对应的方法数。
f[n-1]----n-1个编号的信放在n-1个编号位置的信封,各不对应的方法数。
错排信件–2058
找规律:
第一步: 把第n封信放在第k个信封(k≠n),不对应的共有n-1种方法。
第二步: 放编号为 k 的信,有两种情况:
1)将编号为 k 的信放到第n个信封,则对于剩下的n-2封信,需要放到剩余的n-2个信封且各不对应—有f[n-2]种方法。
2)将编号为 k 的信不放到位置n(1不对1,2不对2,k不对n…),对于这n-1封信,放到剩余的n-1个信封且各不对应,有f[n-1]种方法。(还是n-1封信对应n-1个信封)
结论: f[n] = (n-1) * (f[n-2] + f[n-1]) //第一 步 共有n-1个 k
特例: f[1] = 0 ,f[2] = 1 ------边界
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int i,n;
long long int f[22];
while(scanf("%d",&n)!=EOF)
{
f[1]=0;
f[2]=1;
for(i=3; i<=n; i++)
{
f[i]=(i-1)*(f[i-1]+f[i-2]);
}
printf("%lld\n",f[n]);
}
return 0;
}
在一场盛大的集体婚礼中,为了使婚礼进行的丰富一些,司仪临时想出了有一个有意思的节目,叫做"考新郎",具体的操作是这样的:
首先,给每位新娘打扮得几乎一模一样,并盖上大大的红盖头随机坐成一排;
然后,让各位新郎寻找自己的新娘.每人只准找一个,并且不允许多人找一个.
最后,揭开盖头,如果找错了对象就要当众跪搓衣板…
看来做新郎也不是容易的事情…
假设一共有N对新婚夫妇,其中有M个新郎找错了新娘,求发生这种情况一共有多少种可能.
输入数据的第一行是一个整数C,表示测试实例的个数,然后是C行数据,每行包含两个整数N和M(1 < M <= N <= 20)
对于每个测试实例,请输出一共有多少种发生这种情况的可能,每个实例的输出占一行。
Sample Input
2
2 2
3 2
Sample Output
1
3
#include <stdio.h>
#include <stdlib.h>
long long int g(int n)
{
if(n==1||n==0)
return 1;
else return n*g(n-1);
}
int main()
{
int i,T,n,m;
long long int C,f[101];
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
f[1]=0;f[2]=1;
for(i=3;i<=n;i++)
{
f[i]=(i-1)*(f[i-1]+f[i-2]);
}
C=g(n)/(g(n-m)*g(m));
printf("%lld\n",C*f[m]);
}
return 0;
}