培训

来源:互联网 发布:飞利浦淘宝授权 编辑:程序博客网 时间:2024/04/19 21:26
    公交车票价为5角。假设每位乘客只持有两种币值的货币:5角、1元。再假设持有5角的乘客有m人,持有1元的乘客有n人。由于特殊情况,开始的时候,售票员没有零钱可找。我们想知道这m+n名乘客以什么样的顺序购票则可以顺利完成购票过程。显然,m < n的时候,无论如何都不能完成,m >=n的时候,有些情况也不行。比如,第一个购票的乘客就持有1元。下面的程序计算出这m+n名乘客所有可能顺利完成购票的不同情况的组合数目。注意:只关心5角和1元交替出现的次序的不同排列,持有同样币值的两名乘客交换位置并不算做一种新的情况来计数。

//m: 持有5角币的人数
//n: 持有1元币的人数
//返回:所有顺利完成购票过程的购票次序的种类数

int f(int m, int n)
{
    if(m < n) return 0;
    if(n==0) return 1;
    return _______________________;
}
// f(m-1, n) + f(m, n-1)

//卡特兰数

http://baike.baidu.com/link?url=jf0KXPi1d4XMDCAwlvpwbti15_GH3oPUkJtUXR8Okf9Krtl6t4Yc6hi2C5sOrRY_wmqLQea5SFBz6P0p96JmJxawph9_kM7Z7un_cv6x2bd891oV6p-9rzX7cD8N49MrNpaqao75QRrIFT8cCgmxJK#4_2



反转串

我们把“cba”称为“abc”的反转串。
下面的代码可以把buf中的字符反转。其中n表示buf中待反转的串的长度。请补充缺少的代码。

把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。

void reverse_str(char* buf, int n)
{
    if(n<2) return;
    char tmp = buf[0];
    buf[0] = buf[n-1];
    buf[n-1] = tmp;
    _______________________________;//reverse_str( buf+1, n -  2);
}


    下列代码把一个二进制的串转换为整数。请填写缺少的语句;

    char* p = "1010110001100";
    int n = 0;
    for(int i=0;i<strlen(p); i++)
    {
        n = __________________;// n + ( p[i] - '0' == 0 ? 0 : pow( 2, strlen(p) - i - 1));
    }
    printf("%d\n", n);



题目描述:

    在我国古代和近代,一直采用干支法纪年。它采用10天干和12地支配合,一个循环周期为60年。

    10天干是:甲,乙,丙,丁,戊,己,庚,辛,壬,癸
    12地支是:子,丑,寅,卯,辰,巳,午,未,申,酉,戌,亥

    如果某年是甲子,下一年就是乙丑,再下是丙寅,......癸酉,甲戌,乙亥,丙子,....

    总之天干、地址都是循环使用,两两配对。

    今年(2012)是壬辰年,1911年辛亥革命

    下面的代码根据公历年份输出相应的干支法纪年。已知最近的甲子年是1984年。

程序分析:

关键点是题目中的“循环使用,两两配对”这句话,循环使用就是除k取余

程序代码:

void f(int year){char* x[] = {"甲","乙","丙","丁","戊","己","庚","辛","壬","癸"};char* y[] = {"子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"};int n = year - 1984;while(n<0) n += 60;printf("%s%s\n", x[n%10], y[n%12]);}int main(int argc, char* argv[]){f(1911);f(1970);f(2012);return 0;}

歌赛新规则

歌手大赛的评分规则一般是去掉一个最高分,去掉一个最低分,剩下的分数求平均。当评委较少的时候,如果我们只允许去掉一个分数,该如何设计规则呢?
有人提出:应该去掉与其余的分数平均值相差最远的那个分数。即“最离群”的分数。

以下的程序用于实现这个功能。其中x存放所有评分,n表示数组中元素的个数。函数返回最“离群”的那个分数值。请补全缺失的代码。

把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。

double score(double x[], int n)
{
    int i,j;
    double dif = -1;
    double bad;
    for(i=0; i<n; i++)
    {
        double sum = 0;
        for(j=0; j<n; j++)
        {
            if(________) sum += x[j];//j != i;
        }
        double t = x[i] - sum / (n-1);
        if(t<0) t = -t;
        if(t>dif)
        {
            dif = t;
            bad = x[i];
            printf("%d, %f\n", i, x[i]);
        }
    }

    return bad;
}



    “考拉兹猜想”(又称3n+1猜想、角谷猜想、哈塞猜想、乌拉姆猜想或叙拉古猜想) 和“哥德巴赫猜想”一样目前还没有用数学方法证明其完全成立。在1930年,德国汉堡大学的学生考拉兹,曾经研究过这个猜想,因而得名。在1960年,日本人角谷静夫也研究过这个猜想。
该猜想的叙述十分简单:从任何一个正整数n出发,若是偶数就除以2,若是奇数就乘3再加1,如此继续下去,经过有限步骤,总能得到1。例如:
17-52-26-13-40-20-10-5-16-8-4-2-1
该猜想虽然没有完全证明,但用计算机验证有限范围的数字却十分容易。以下是验证的代码,请补全缺少的部分。

    for(int n=2; n<=10000; n++)
    {
        int m = n;
        for(;;)
        {
            if(____________)// !(m %2);
                m = m / 2;
            else
                m = m * 3 + 1;
            if( m == 1 )
            {
                printf("%d ok! \n", n);
                break;
            }
        }
    };



    1+3 = 4,  1+3+5 = 9,  1+3+5+7 = 16 它们的结果都是平方数。这是偶然的巧合吗?下面代码验证对于累加至1000以内的情况都成立。试完善之。

    int n = 1;
    for(int i=1; i<1000/2; i++)
    {
        n += 2 * i + 1;
        int m = ______________;//i+1
        if( m * m != n)
        {
            printf("加至%d 时不成立!\n", 2 * i + 1);
            break;
        }
    }



开平方

如果没有计算器,我们如何求2的平方根?
可以先猜测一个数,比如1.5,然后用2除以这个数字。如果我们猜对了,则除法的结果必然与我们猜测的数字相同。我们猜测的越准确,除法的结果与猜测的数字就越接近。
根据这个原理,只要我们每次取猜测数和试除反馈数的中间值作为新的猜测数,肯定更接近答案!这种计算方法叫做“迭代法”。

下面的代码模拟了如何用手工的方法求2的平方根的过程。请填写缺少的代码。

把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。

    double n = 2;
    double a = 0;
    double b = n;
    while(fabs(a-b)>1E-15)
    {
        a = (a+b)/2;
        b = __________;// n/a;
    }
    printf("%f\n", a);


    给定一个串,例如“aabbbcddddkkkmmmmaakkkk”我们希望去掉连续的重复字母,得出

串:“abcdkmak”,下面代码实现了该功能,请完善之。

    char* p = "aabbbcddddkkkmmmmaakkkk";
    char buf[100];

    char* q = p;
    int i=0;
    for(;*q;)
    {
        if(___________|| *q != *(q-1))// p == q;
        {
            buf[i++] = *q;
        }
        q++;
    }
    buf[i] = '\0';

    printf("%s\n", buf);



人类历史上出现了很多种历法。现行的公历即格里历由儒略历改革而来。它是目前较为精确和规则简明的一种历法,约3300年误差一日。因为闰年问题以及每个月的长度不等,仍然使得某些

计算较为麻烦。比如:求两个日期间差多少天。
下面的代码实现了求两个由公历表示的日期间差多少天的功能。
其计算原理是先求出每个日期距离1年1月1日的天数差值,再进一步做差即可。
请研读代码,填写缺失的部分。

把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。

struct MyDate
{
    int year;
    int month;
    int day;
};

int GetAbsDays(MyDate x)
{
    int i;
    int month_day[] = {31,28,31,30,31,30,31,31,30,31,30,31};
    int year = x.year-1;  // 因为欲求距离1年1月1日的距离
    int days = year * 365 + year/4 - year/100 + year/400;                                                  //除去最后一年的天数
    if(x.year%4==0 && x.year%100!=0 || x.year%400==0) month_day[1]++;               //最后一年是否是闰年
    for(i=0; i<______________; i++) //x.month-1                                                           //最后一年除最后一个月的天数
        days += month_day[i];
    days += x.day-1;
    return days;
}

int GetDiffDays(MyDate a, MyDate b)
{
    return GetAbsDays(b) - GetAbsDays(a);
}

int main(int argc, char* argv[])
{
    MyDate a = {1842,5,18};
    MyDate b = {2000,3,13};
    int n = GetDiffDays(a,b);
    printf("%d\n", n);
}

    生活中人们往往靠直觉来进行粗略的判断,但有的时候直觉往往很不可靠。比如:如果你们班有30名同学,那么出现同一天生日的概率有多大呢?你可能不相信,这个概率高达70%左右。

以下的程序就是用计算机随机模拟,再统计结果。仔细阅读代码,补全空白的部分。

#define N 30
......
    int a[N];
    srand( time( NULL ) );
    int n = 0;
    for(int k=0; k<10000; k++)
    {
        for(int i=0; i<N; i++)
            a[i] = rand() % 365;
        bool tag = false; // 假设没有相同
        for(i=1; i<N; i++)
        {
            for(int j=0; j<i; j++)
            {
                if(a[i]==a[j])
                {
                    tag = true;
                    break;
                }
            }
            _____________________;// if ( tag) break                找到相同退出循环
        }
        if(tag) n++;
    }

    printf("%f\n", 1.0 * n / 10000 * 100);


    任意给定一个4位数(不能所有位都相同),比如:3278,重新组合出最大数:8723,再重新组合出最小数:2378,相减,得到新的4位数(如不足则补0),重复这个过程,最后必然得到一个数字:6174。这个现象被称为:数字黑洞。下面的函数实现由给定的4位整数求出下一个整数的功能。请完善之。

int f(int n)
{
    int N[4];
    for(int i=0; i<4; i++)
    {
        N[3-i] = n % 10;
        ___________________;//n/=10
    }

    for(i=0; i<3; i++)
        for(int j=0; j<3-i; j++)
            if(N[j]>N[j+1])
            {
                int t = N[j+1];
                N[j+1] = N[j];
                N[j] = t;
            }
            
    int n_min=0;
    for(i=0; i<4; i++)
        n_min = n_min * 10 + N[i] ;
    int n_max = 0;
    for(i=3; i>=0; i--)
        n_max = n_max * 10 + N[i];

    return n_max-n_min;
}




数论中有著名的四方定理:所有自然数至多只要用四个数的平方和就可以表示。
我们可以通过计算机验证其在有限范围的正确性。

对于大数,简单的循环嵌套是不适宜的。下面的代码给出了一种分解方案。

请仔细阅读,填写空缺的代码(下划线部分)。

注意:请把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。
直接写在题面中不能得分。

int f(int n, int a[], int idx)
{
    if(______________) return 1;  // 填空1    0 == n
    if(idx==4)  return 01;

    for(int i=(int)sqrt(n); i>=1; i--)
    {
        a[idx] = i;

        if(_______________________)  return 1;  // 填空2    f( n - i * i, a, idx+1)
    }

    return 0;
}

int main(int argc, char* argv[])
{
    for(;;)
    {
        int number;
        printf("输入整数(1~10亿):");
        scanf("%d",&number);
        
        int a[] = {0,0,0,0};

        int r = f(number, a, 0);

        printf("%d: %d %d %d %d\n", r, a[0], a[1], a[2], a[3]);
        
    }

    return 0;
}



    因数分解是十分基本的数学运算,应用广泛。下面的程序对整数n(n>1)进行因数分解。比如,

n=60, 则输出:2 2 3 5。请补充缺失的部分。

void f(int n)
{
    for(int i=2; i<n/2; i++)
    {
        ____________________while( ! (n % i))
        {
            printf("%d ", i);
            n = n / i;
        }
    }
    if(n>1) printf("%d\n", n);
}


如果一个自然数的平方数的尾部仍然为该自然数本身,则称其为自守数。
例如:
5 x 5 = 25
76 x 76 = 5776
625 x 625 = 390625

下面代码的目的是寻找出2千万以内的所有自守数。

注意,2千万的平方已经超出了整数表达的最大范围,所以该程序使用了一个巧妙的方案。
如果我们仔细观察乘法的计算过程,就会发现实际上对乘积的尾数有贡献的环节,从而不用真正计算出

整个乘积。

请分析代码并填写缺失的部分。

注意:请把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中

即可。
直接写在题面中不能得分。


void zishou()
{
    int n;
    for(n=1; n<20 * 1000 * 1000; n++)
    {
        int n2 = n;  
        int m = 0;
        for(;;)
        {
            if(n2==0)
            {
                printf("%d\n", n);
                break;
            }
            
            int k = n2 % 10;  // 从末尾开始,取出乘数的每位数字
            m += k * n;  // 累计乘积
            if(_________________) break;        // m / 10 != k
            m = m / 10;  // 舍去累计乘积的末位
            n2 = _______________;              // n2 / 10
        }
    }
}


金字塔

下面代码的目标是输出一个大写字母组成的金字塔。
其中space表示金字塔底距离左边的空白长度,x表示金字塔底的中心字母。
比如:space=0, x=’C’,则输出:
  A
 ABA
ABCBA
再如:space=2,x=’E’, 则输出:
      A
     ABA
    ABCBA
   ABCDCBA
  ABCDEDCBA

请分析该段代码的逻辑,填写缺少的部分。
把填空的答案(仅填空处的答案,不包括题面)存入考生文件夹下对应题号的“解答.txt”中即可。
void h(int space, char x)
{
    int i;
    if(x<'A' || x>'Z') return;
    _______________;                // h( space + 1, x - 1)
    for(i=0; i<space; i++) printf(" ");
    for(i=0; i<x-'A'; i++) printf("%c",'A'+i);
    for(i=0; i<=x-'A'; i++) printf("%c",______);    // x - i
    printf("\n");
}














0 0