12月份大一周赛解题报告

C 题---Oh, my God!

题目链接: click here

题目翻译:首先,所有参加晚会的人员都将一张写有自己名字的字条放入抽奖箱中;
然后,待所有字条加入完毕,每人从箱中取一个字条;
最后,如果取得的字条上写的就是自己的名字,那么“恭喜你,中奖了!”
求计算一下发生这种情况的概率吗?
看到大家错了好多次,应该是没认真读题目要求,注意是要求所有人都选到自己名字的概率,而不是求一个人。
用到错排公式,
总体上就是得出n的完全错排方案个数, 然后除以n!即可;关键是求n的完全错排方案个数;
第n个人可以选取前n-1个人中任意一个人的字条,  第n个人有n-1种选择,
假设第n个人取到的是第i个人的字条,这时i可以保留第n个人的字条,剩余的n-2个人完全错排;
若i未保留第n个人的字条,则是除第n个人之外的剩余n-1个人完全错排!递推公式为:f(n) = (n-1)*(f(n-1) + f(n-2));  用到两个数组,注意输出有个小数点。
 参考代码:

#include<stdio.h>
int main()
{
    // freopen("1.txt","r",stdin);
    //freopen("2.txt","w",stdout);
    int i,c,n,cc=1;
    double a[21],b[21];
    a[0]=1;
    for(i=1; i<21; i++)
        a[i]=a[i-1]*i;
    b[1]=0;
    b[2]=1;
    b[3]=2;
    for(i=3; i<21; i++)
        b[i]=(i-1)*(b[i-1]+b[i-2]);
    while(~scanf("%d",&n)&&n)
    {
       //scanf("%d",&n);
       printf("Case [%d]: ",cc++);
       if(n==1)
        printf("100.00%%.\n");
       else
    printf("%.2lf%%.\n",b[n]*100/a[n]);
    }
    return 0;
}

E 题---Oh, my Paper!

链接: click here

题意很清晰,
给你一张纸,n(行)*m(列)你要计算的是
算出从一个对角线到另一个对角线有多少走法(只能向上,向右走)。
分析:一个矩阵,它有行有列,要到达对角线,必定有通过所有的行和列,那么存在两种情况,当行(n)==列(m),即刚好走完列和行,在m+n个里选m或n个组合得C(m+n,m)或C(m+n,n)。
当两者不相等,就要看那个先到,所有最小的必定先到达。
另外数据应用unsigned型,它比int型存储的数要大1倍。
参考代码:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef unsigned long long LL;
//#define  LL long long
int main()
{
    //freopen("3.txt","r",stdin);
    //freopen("4.txt","w",stdout);
	double sum;
	unsigned n,m,a,b;
	while(scanf("%d%d",&n,&m),n||m)
	{
		a=n+m;
		b=n<m?n:m;
		sum=1;
		while(b>0)
		 sum*=a--/double(b--);
		printf("%.0f\n",sum);
     }
	return 0;
}

你可能感兴趣的:(ACM,解题报告)