2016/7/6 实验

来源:互联网 发布:mac上文件变成exe 编辑:程序博客网 时间:2024/06/06 03:35

hdu 2048

题目的主要问题就是求N张字条的错排数f(N)(分子)。
首先,如果前面N-1个人拿的都不是自己的票,即前N-1个人满足错排,现在又来了一个人,他手里拿的是自己的票。只要他把自己的票与其他N-1个人中的任意一个交换,就可以满足N个人的错排。这时有(N-1)*f(N-1)种方法。

同时,如果前N-1个人不满足错排,而第N个人把自己的票与其中一个人交换后恰好满足错排。

这种情况发生在原先N-1人中,N-2个人满足错排,有且仅有一个人拿的是自己的票,而第N个人恰好与他做了交换,这时候就满足了错排。
又因为前N-1个人中,每个人都有机会拿着自己的票。所以有N-1种交换的可能。故这时有(N-1)*f(N-2)种方法。

所以:f(N)=(N-1)*[f(N-1)+f(N-2)] 

代码:

#include "cstdio"#include "algorithm"using namespace std;typedef long long ll;ll f[21], sum;int main(){int i, t, n;f[1] = 0; f[2] = 1;for (i = 3; i<21; i++)f[i] = (i - 1)*(f[i - 1] + f[i - 2]);scanf("%d", &t);while (t--){scanf("%d", &n);sum = 1;for (i = 1; i <= n; i++)sum *= i;printf("%.2lf%%\n", f[n] * 100.0 / sum);}return 0;}



hdu 2049

和上一题相似,加入了排组
N个新郎中M个错排是CMN=N!/(M!*(N-M)!)。即CMN=N!/M!/(N-M)!。
#include "cstdio"#include "cstdlib"typedef long long ll;int main(){int  n, m, i;ll a[25], b[25];a[0] = 1; a[1] = 1, a[2] = 2;for (i = 3; i < 21; i++)a[i] = a[i - 1] * i;b[0] = 0; b[1] = 1; b[2] = 1, b[3] = 2;for (i = 4; i < 21; i++)b[i] = (i - 1)*(b[i - 1] + b[i - 2]);int t;scanf("%d", &t);while (t--){scanf("%d%d", &n, &m);printf("%lld\n", a[n] / a[m] / a[n - m] * b[m]);}return 0;}




0 0
原创粉丝点击