首页 > 代码库 > 12月份大一周赛解题报告

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);
    LL n, m;
    while(cin>>n>>m)
    {
        if(n==0&&m==0) break;
        LL s=n+m;
        if(n>m) swap(n,m);
        LL ans=1;
        for(LL i=s, j=1; j<=n; i--, j++)
        {
            ans=ans*i/j;//数据很大,所以采用边乘边除
        }
        cout<<ans<<endl;
    }
    return 0;
}









12月份大一周赛解题报告