天天看点

东华大学2020考研计算机复试准备上机题解析答案_进阶篇(31-60)

文章目录

    • 前言
    • 31 最高频率
    • 32 三艘船
    • 33 回文数
    • 34 特殊四位数
    • 35 最大值
    • 36 数列1
    • 37 混合牛奶
    • 38 修理牛棚
    • 39 奇妙的数字
    • 40 按要求输出序列
    • 41 部落人乘法
    • 42 数列2
    • 43 序列
    • 44 双重回文数
    • 45 等差数列
    • 46 人见人爱A-B
    • 47 最少拦截系统
    • 48 求N!
    • 49 我素故我在
    • 50 素数
    • 51 歌德巴赫猜想
    • 52 N的倍数
    • 53 求n天后的日期
    • 54 菱形输出
    • 55 三角形的个数
    • 56 汉诺塔问题的第m步
    • 57 数字游戏
    • 58 矩阵转换
    • 59 魔方阵
    • 60 最大效益

前言

提交代码:

选择

C++

编程语言,因为有的时候会用到C++的一些方便的头文件什么的,还有我编写代码是有一部分是纯C的,因为做题来讲C的scanf和printf很方便。

发布文章安排:

我会抽时间发文章的,看时间安排了,现在时间有点紧吧。马上过年了。过完年要开始准备准备其他东西了

解题解法质量:

关于我的解法和代码的精简程度,我是以当时做题的心态来解题的,由于当时急着刷完所有题目,所以难免会有一些题应该有其他更优的解法,我却用了比较暴力一点的,毕竟当时的劳动强度有点大,抓进度来着,如果有更好的解法,欢迎联系我,或者直接评论,共同学习,共同进步!

联系方式:

如果有问题交流咨询,可以加入QQ群:

673852347

其他未尽事宜,还望海涵!

31 最高频率

作者: 朱凯 时间限制: 10S 章节: 一维数组

问题描述 :

明明的爸爸是一位著名的数学家。他在明明很小的时候就发现明明有过人的数学天赋,因此有意培养他对数学的兴趣。一次,明明的爸爸和明明玩起了一个数字游戏,这个游戏的名字叫“最高频率”。在游戏中,明明的爸爸要求明明在一串数字中,找出出现次数最多的那个数字,如果有多个数字出现的次数一样,则取最小的那个数字。明明很快就理解的游戏的规则,开始玩起来。明明的爸爸首先给了明明三个数字:3、2、1;明明很快就回答说:“1”(虽然3、2都出现一次,但是1是最小的数字,因此答案是1)。明明的爸爸很惊讶于明明的反应速度,开始加大游戏的难度,给出了由6个数字组成的数字串:2、1、3、4、5、2;明明眼珠子一转,脱口而出:“2”。明明的爸爸意识到简单的数字串很难难住明明,于是决定给出很长的一串字符串来考明明。但与此同时,明明爸爸面对这很长的数字串,也无法一时就统计出哪个数字出现的次数最高。于是就求助于你,让你帮他写一个程序,用来计算出出现次数最多的那个数字。 明明的爸爸的问题可以归结为:给你一个数字串,里面有n个数字,输出这个数字串中出现次数最多的那个数字;如果有多个数字出现次数一样,则输出其中最小的那个数字。

输入说明 :

你写的程序需要从标准输入设备(通常为键盘)中读入多组测试数据,每组测试数据仅占一行,每行开始有一个正整数n(1 ≤ n ≤ 200),表示数字串中有n个数字;之后有n个数字,表示数字串中的n个数,其中每个数都大于等于1且小于等于109;每个数字之间用一个空格隔开。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明 :

对于每一组测试数据,你写的程序需要计算出一组相应的运算结果,并将每组运算结果依次写入到标准输出设备(通常为启动该程序的文本终端,例如Windows中的命令行终端)中。每组运算结果为一个整数,即这个数字串中出现次数最多的那个数字;如果有多个数字出现次数一样,则输出其中最小的那个数字。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。

输入范例 :

1 100

5 5 3 77 23 10

输出范例 :

100

3

#include<stdio.h>// summershell
int main()//水题
{
    int N,a[2020],temp;
    while(scanf("%d",&N)!=EOF)
    {
        for(int i=0;i<2020;i++)a[i]=0;
        for(int i=0;i<N;i++){scanf("%d",&temp);a[temp]++;}
        int maxp=-10,maxn=0;
        for(int i=0;i<2020;i++)if(maxp<a[i]){maxp=a[i];maxn=i;}
        printf("%d\n",maxn);
    }
    return 0;
}
           

32 三艘船

作者: 朱星垠 时间限制: 10S 章节: 一维数组

问题描述 :

明明由于工作的关系,经常需要坐船到某地出差办事。久而久之,明明就对这两地之间船的班次情况相当了解,他会根据办事的具体情况选择不同班次的船出行。这两地的船一共分为三个班次:特快船、快船、慢船,三个班次的船在同一天的0点从港口出发,并沿着同一路线匀速航行,只是它们到达目的地的时刻不同。 你作为明明的好朋友,有一次和明明在闲聊,问到他出差时船的航行距离有多少时,明明没有正面回答你这个问题,而只是把三艘船(特快、快、慢)的速度,以及它们到达目的地的时间是几点钟(并不知道分别是哪一天,只知道三艘船都在100天以内到达了终点)告诉了你,要你推算出两地间的距离长度。你作为一位程序设计专家,自然不会被明明的这个问题所难倒,于是你决定写一个程序,来求解这个看似困难其实简单的问题。 明明的问题可以归结为:给出三艘船的速度,以及它们到达目的地时是几点钟(并不知道分别是哪一天,只知道三艘船都在100天以内到达了终点),求两地间的距离到底有多少。若有多组解,只输出最小的那组解。

输入说明 :

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据占二行,第一行有3个正整数a、b、c,代表3艘船的到达港口那天的时间是几点钟(0≤a、b、c≤23)。第二行有3个正整数d、e、f代表3艘船的速度(0<d、e、f<30000),速度的单位是单位距离每小时。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明 :

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果由一个整数构成,代表路程的长度,若有多组解,只输出最小的那组解。每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。

思路:

很简单 暴力来解 枚举每个距离 看那个符合条件 用模除运算来解决

#include<stdio.h>// summershell
struct node
{
    int x,y;
}a[4];
int main()
{
    int i;
    while(scanf("%d %d %d",&a[0].x,&a[1].x,&a[2].x)!=EOF)
    {
        scanf("%d %d %d",&a[0].y,&a[1].y,&a[2].y);
        if(a[0].y>a[1].y){a[3]=a[0];a[0]=a[1];a[1]=a[3];}//排好序
        if(a[1].y>a[2].y){a[3]=a[1];a[1]=a[2];a[2]=a[3];}
        if(a[0].y>a[1].y){a[3]=a[0];a[0]=a[1];a[1]=a[3];}
        for(i=1;i<3000000;i++)
        {//咱也没啥大本事,只能会暴力循环才勉强AC的样子
            if(i%(a[0].y)==0 && i%(a[1].y)==0 && i%(a[2].y)==0)
            {
                int m1=i/a[0].y,m2=i/a[1].y,m3=i/a[2].y;
                if(m1%24==a[0].x && m2%24==a[1].x && m3%24==a[2].x)
                {
                    printf("%d\n",i);
                    break;
                }
            }
        }
    }
    return 0;
}
           

如果有问题交流咨询,可以加入QQ群:

673852347

33 回文数

作者: ZhouMingLiang 时间限制: 10S 章节: 一维数组

问题描述 :

有一天,明明在做数学作业的时候,发现了一组很有趣的数字。例如1、11、121、1331等等。他发现这些数字都是左右对称的,即不管你把这些数字从左读到右还是从右读到左,读出来的数字都是一样的。于是明明就把这个发现告诉了他爸爸。明明的爸爸是一名数学专家,他当然对这种类型的数字早有研究,他对明明说:“这些是回文数,它是一种特殊的数字现象,即这些数字的左右两边是对称的。例如:121左右两边对称,1331左右也是对称的。”明明觉得这很有趣,接着问他爸爸还有什么和这类回文数有关的好玩的东西,明明的爸爸于是就教了明明一种方法,这种方法是从任意一个整数出发,经过某种计算,就可以得到一个回文数。 这个方法如下: 例如首先给你一个数19,然后把它的最低位与最高位交换(如果还有更多位,则次低位与次高位交换…),得到它的逆序数91,然后两数相加,即19+91=110,我们得到110,因为110不是回文数,因此我们继续上面的步骤,110+11=121,现在我们就得到了一个回文数121。通过这种方法,我们就可以求得一个与某一个整数有关的回文数。 明明很聪明,很快就掌握了这个方法,但是他也发现了一个问题,就是有时候计算一个回文数,需要重复很多次以上的步骤,这使得明明很烦恼。于是他就求助于你,请你帮他写一个程序,通过程序来完成以上求回文数的过程。

明明的问题可以归结为:给你一个整数,通过上面叙述的求回文数的方法,求出回文数,并输出求解过程。输入数据保证该回文数小于2^31

输入说明 :

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行有一个整数n(10≤n≤10000),即要求回文数的那个整数。当n=0时,表示输入结束。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明 :

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一行或多行的回文数求解过程,直到求出回文数为止。每行的格式如下a+b=c,其中a是原来的数,b是a的交换后的那个数,c是a+b的结果,详细格式请参考输出样例。每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。 注:通常,显示屏为标准输出设备。

思路:

加个逆序处理函数就好了 注意前导0的处理

#include<stdio.h>// summershell
int huiwen(int a)//利用栈判断回文,判断回文的方法有多种,栈比较方便吧
{
    int stack[100],top=-1,temp=a;
    while(temp)
    {
        stack[++top]=temp%10;
        temp/=10;
    }
    while(top!=-1)
    {
        if(stack[top--]!=a%10)return 0;
        a/=10;
    }
    return 1;
}
int rever(int a)//利用队列逆转
{
    int queue[100],front=0,rear=0,temp=a,i;
    while(temp)
    {
        queue[rear++]=temp%10;
        temp/=10;
    }
    while(front!=rear)
        temp=temp*10+queue[front++];
    return temp;
}
int main()
{
    int N,a,b,c;
    while(scanf("%d",&N)!=EOF && N)
    {
        c=N;
        do
        {
            a=c;b=rever(a);c=a+b;
            printf("%d+%d=%d\n",a,b,c);
        }while(!huiwen(c));
    }
    return 0;
}
           

如果有问题交流咨询,可以加入QQ群:

673852347

34 特殊四位数

作者: 孙辞海 时间限制: 10S 章节: 一维数组

问题描述 :

数学一直是明明很喜欢的一门学科,不但上课认真听讲,而且还自己钻研。有一次,老师在课上讲了一种特殊的四位整数,这种整数有两个特性:

第一,它是某一个自然数的平方;

第二,它的千位数字与十位数字之和等于百位数字与个位数字之积。

然后老师就举了一个例子:1156,1156是34的平方,且1156的千位数字1加上十位数字5等于百位数字1乘以个数数字6,即1+5=16。

然后老师告诉同学,这是最小的一个符合以上两个特性的四位整数,接着老师就留下了作业,要让同学们回家后尽量多的找出符合这两个特性的特殊四位数。明明回家后,就开始找了起来,1157、1158、1159、……、3136,直到到了3136(3136=5656,3+3=1*6),明明才找到了第二个这样的特殊四位数。明明觉得这样找下去不是办法,后面还有好几千个数字要一个一个试下来,这样一定无法在睡觉前完成。于是明明就求助于你,帮他写一个程序,从小到大求出所有的这样的特殊四位数,然后当明明想要第几个这样的特殊四位数时,你就能够很快的告诉他。 如果把上述所有的特殊四位数按从小到大的顺序排列后记为S1,S2,…,Sn,…,即排在第1个位置上的特殊四位数记为S1,排在第2个位置上的特殊四位数记为S2,…,排在第n个位置上的特殊四位数记为Sn,那么明明的问题可以归结为:假如一个特殊四位数排在第n个位置上,那么这个特殊四位数Sn等于多少呢?

输入说明 :

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行仅有一个正整数n(n不大于特殊四位数的个数),表示要求第n个特殊四位数Sn。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明 :

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个正整数,表示与输入数据n相对应的那个特殊四位数Sn,每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
int judge(int x)//千十和==百个积
{
    return x/1000+(x/10)%10==(x%10)*((x/100)%10)?1:0;
}
int main()//如果从1156找到9999,那么开方很麻烦,不妨从34*34到99*99入手
{
    int N,a[1000],counter=1;
    for(int i=34;i<100;i++)
        if(judge(i*i))a[counter++]=i*i;
    while(scanf("%d",&N)!=EOF)
        printf("%d\n",a[N]);
    return 0;
}
           

35 最大值

作者: frankhuhu 时间限制: 10S 章节: 一维数组

问题描述 :

为了培养明明对数学的热爱,明明的爸爸经常想出一些简单有趣且富有数学思想的游戏给明明玩。有一次,明明的爸爸在纸上写了N个数字,有正整数、负整数和0。明明的爸爸给明明一个范围,他可以选大于等于L1个且小于等于L2个的数字(L1≤L2),且这些数字必须是连续的。但是要求明明选出的数的和最大,这样说明明可能不太明白,于是明明爸爸就举了一个简单的例子。 例如有5个数字为“1”、“2”、“3”、“4”、“5”,明明可以选择大于等于1个且小于等于2个的数字,也就是说明明可以选择1个数字,或者连续的2个数字。通过观察数字串,最后我们会选2个数字,4和5,他们的和最大,为9。 明明明白爸爸的意思后,就开始玩起游戏来。但是他发现,这个游戏看似简单,其实还是有相当的难度,因为数字越多,选择数字个数范围越大,则题目越难,到后面明明有些不想玩了。于是明明就求助于你,请你帮他写一个程序,来求出和的最大值。 明明的问题可以归结为:有N个数字,从中选择出连续的M(L1≤M≤L2)个数,求出它们之和的最大值。

输入说明 :

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据有两行,每组测试数据的第一行有三个整数N(0<N≤20)、L1、L2(0<L1≤L2≤N),N表示数字串中有多少个整数,L1、L2表示可选数字个数的范围,每组测试数据的第二行有N个整数,整数大小的绝对值都小于等于100,整数之间用一个空格隔开。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明 :

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个整数,即所求的最大值。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
int fun(int a[],int N,int len)
{
    int maxnum=-9999999,sum;
    for(int i=0;i+len-1<N;i++)
    {
        sum=0;
        for(int j=0;j<len;j++)sum+=a[j+i];
        if(sum>maxnum)maxnum=sum;
    }
    return maxnum;
}
int main()//这道题,在基础篇里面做过,当时是循环遍历
{
    int N,L1,L2,a[2020];
    while(scanf("%d %d %d",&N,&L1,&L2)!=EOF)
    {
        for(int i=0;i<N;i++)scanf("%d",&a[i]);
        int maxn=-9999999;
        for(int i=L1;i<=L2;i++)
        {
            int temp=fun(a,N,i);
            if(temp>maxn)maxn=temp;
        }
        printf("%d\n",maxn);
    }
    return 0;
}
           

36 数列1

作者: frankhuhu 时间限制: 10S 章节: 一维数组

问题描述 :

思维的严密性是相当重要的,尤其是在程序设计中,一个小小的错误,就可能导致无法想象的后果。明明的爸爸是一名富有经验的程序设计专家,深知思维严密的重要性。于是在明明很小的时候,就通过游戏的方式训练明明的思维严密性。今天,明明的爸爸和明明做了一个数列的游戏。

这个游戏很简单,就是有一数列,现在需要在数列中选出一个或者连续若干个数,要求这些数的和能被11整除。明明的爸爸想锻炼明明思维的严密性,因此要求明明尽可能多的找出符合条件的数列来,最好一个也不要漏掉。 例如有一数列为“11 22 33”,其中11可以被11整除,22可以被11整除,33可以被11整除,11+22=33能被11整除,22+33=55能被11整除,11+22+33=66能被11整除。所以以上一数列能被11整除的情况一共有六种。(注:虽然11+33也能被11整除,但是11和33在数列中没有连续出现,因此不算一种合理的情况。) 明明对这个游戏很感兴趣,高兴地玩了起来。由于粗心,明明总是无法一次就把所有的情况都找出来,这使得他爸爸不是很满意。于是明明爸爸决定先降低游戏的难度,事先告诉明明某一数列总共有多少种符合条件的选择数的方法,然后再让明明去选。明明的爸爸请你帮一个忙,他不想自己找出所有的情况,因此请你写一个程序,用程序来找出一共有多少种符合选数的情况,并把结果告诉他。 明明爸爸的问题可以归结为:给你一个数列,从中选出1个或连续若干个数,要求这些数的和能被11整除,问这样的选数方法一共有多少种。

输入说明 :

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据有两行,每组测试数据的第一行有一个整数n(0<n≤50),表示数字串中有多少个整数,每组测试数据的第二行有n个整数,整数大于等于0且小于等于100,整数之间用一个空格隔开。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明 :

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个整数,即表示一共有多少种选数方法。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
int counter=0;
void fun(int a[],int N,int start)
{
    int temp;
    for(int len=1;start+len<=N;len++)//增加长度,逐个尝试
    {
        temp=0;
        for(int j=0;j<len;j++)temp+=a[j+start];
        if(temp%11==0)++counter;
    }
}
int main()//这道题,在基础篇里面做过,当时是循环遍历
{
    int N,a[2020];
    while(scanf("%d",&N)!=EOF)
    {
        for(int i=0;i<N;i++)scanf("%d",&a[i]);
        counter=0;
        for(int i=0,j,len;i<N;i++)//每次的起点都不同
            fun(a,N,i);
        printf("%d\n",counter);
    }
    return 0;
}
           

37 混合牛奶

作者: xxx 时间限制: 1S 章节: 结构体

问题描述 :

牛奶包装是一个如此低利润的生意,所以尽可能低的控制初级产品(牛奶)的价格变得十分重要。请帮助快乐的牛奶制造者(Merry Milk Makers)以可能的最廉价的方式取得他们所需的牛奶。快乐的牛奶制造公司从一些农民那购买牛奶,每个农民卖给牛奶制造公司的价格不一定相同。而且,如一头母牛一天只能生产一定量的牛奶,农民每一天只有一定量的牛奶可以卖。每天,快乐的牛奶制造者从每个农民那购买一定量的牛奶,少于或等于农民所能提供的最大值。给出快乐牛奶制造者的每日的牛奶需求,连同每个农民的可提供的牛奶量和每加仑的价格,请计算快乐的牛奶制造者所要付出钱的最小值。注意: 每天农民生产的牛奶的总数对快乐的牛奶制造者来说足够的。

输入说明 :

第 1 行:二个整数, N 和 M。

第一个数值N(0<= N<=2,000,000)是快乐的牛奶制造者的一天需要牛奶的数量。第二个数值,M,(0<= M<=5,000)是农民的数目。

第 2 到 M+1 行:每行二个整数:Pi 和 Ai。 Pi(0<= Pi<=1,000) 是农民 i 牛奶的价格。 Ai(0<= Ai <= 2,000,000)是农民 i 一天能卖给快乐的牛奶制造者的牛奶数量。

输出说明 :

单独的一行包含单独的一个整数,表示快乐的牛奶制造者拿到所需的牛奶所要的最小费用

#include<stdio.h>// summershell
#include<stdlib.h>
int cmp(const void *a,const void *b)
{
    if (((int *)a)[0]!=((int *)b)[0])//指针的魅力鸭
        return ((int *)a)[0]-((int *)b)[0];
    else return 1;
}
int main()//这道题怎么又是重复的题
{
    int N,M,a[5001][2];
    while(scanf("%d %d",&N,&M)!=EOF)
    {
        for(int i=0;i<M;i++)scanf("%d %d",&a[i][0],&a[i][1]);
        qsort(a,M,sizeof(a[0]),cmp);
        int sum=0,i=0;//总钱和第几位农民
        while(N)//开始买了
        {
            if(N>a[i][1])
            {
                sum+=a[i][0]*a[i][1];
                N-=a[i][1];
                ++i;
            }
            else
            {
                sum+=a[i][0]*N;
                break;
            }
        }
        printf("%d\n",sum);
    }
    return 0;
}
           

如果有问题交流咨询,可以加入QQ群:

673852347

38 修理牛棚

作者: xxx 时间限制: 1S 章节: 一维数组

问题描述 :

在一个暴风雨的夜晚,农民约翰的牛棚的屋顶、门被吹飞了。 好在许多牛正在度假,所以牛棚(牛棚的总数S:1<= S<=200)没有住满。 剩下的牛一个紧挨着另一个被排成一行安置在有屋顶的牛棚来过夜。 所以有些牛棚里有牛,有些没有。

所有的牛棚有相同的宽度,且宽度设为1。 因为有些门遗失,农民约翰需要架起新的木板作为门。 他的新木材供应者将会供应他任何他想要的长度,但是供应者只能提供有限数目的木板。 农民约翰想将他购买的木板总长度减到最少。

计算拦住所有有牛的牛棚所需木板的最小总长度。

输出所需木板的最小总长度作为的答案。

说明:拦住一个牛棚需要的木板长度为1,拦住相邻的三个牛棚则需要木板长度为3。

比如有牛的牛棚编号为:

3 5 8 10 11

并且只能使用两块木板,

则第一块木板从3到5,长度为3,

第二块木板从8到11,长度为4,

因此,需要木板的总长度为7。

输入说明 :

第 1 行: M 和 C(用空格分开)

第 2 到 C+1行: 每行包含一个整数,表示牛所占的牛棚的编号。

其中:

可能买到的木板最大的数目:M(1<= M<=50);

需要安置的牛的数目C(1<= C <=S)

安置后牛所在的牛棚的编号stall_number(1<= stall_number <= S)。

输出说明 :

单独的一行包含一个整数表示所需木板的最小总长度

#include<stdio.h>// summershell
#include<stdlib.h>
#include<algorithm>//min函数
int cmp(const void *a,const void *b)
{
    if ((*(int *)a)!=(*(int *)b))
        return (*(int *)a)-(*(int *)b);
    else return 1;
}
int main()//dp一下dp[i][j]表示第i个牛用j个板子需要的最小长度
{
    int C,M,a[2020],dp[210][51];
 //   freopen("in.txt","r",stdin);
    while(scanf("%d %d",&M,&C)!=EOF)
    {
        for(int i=1;i<=C;i++)
            scanf("%d",&a[i]);
        qsort(a+1,C,sizeof(a[0]),cmp);
        for(int i=1;i<=M;i++)
        dp[1][i]=1;//1个牛1个板子最少需要1长度
        for(int i=2;i<=C;i++)
        {
            for(int j=1;j<=M;j++)
            {
                if(j==1)//特殊处理,一个板子时候只能全伸长
                    dp[i][j]=dp[i-1][j]+a[i]-a[i-1];
                else
                dp[i][j]=std::min(dp[i-1][j-1]+1,dp[i-1][j]+a[i]-a[i-1]);//比较上个状态到这个状态之间哪个最优
            }
        }
        int minnum=10000000;
        for(int i=1;i<=M;i++)if(minnum>dp[C][i])minnum=dp[C][i];
        printf("%d\n",minnum);
    }
    return 0;
}
           

如果有问题交流咨询,可以加入QQ群:

673852347

39 奇妙的数字

作者: Hu Yongjian 时间限制: 1S 章节: 一维数组

问题描述 :

有一种自然数,它的各位数字之和能被17整除。这个数的后继数(即这个数加1)的各位数字之和也能被17整除。求所有自然数中,从小到大第n个这样的数。

输入说明 :

你的程序需要从标准输入设备(通常为键盘)中读入多组测试数据。每组输入数据占一行,其中仅有一个整数n(1≤n≤10)。在行首和行尾没有多余的空格。所有数据前后没有多余的空行,两组数据之间也没有多余的空行。

输出说明 :

对每组测试数据,你的程序需要向标准输出设备(通常为启动该程序的终端)依次输出一组对应的答案。每组答案占一行,每行中仅有一个整数,即题目描述中的第n个数。在行首和行尾不要输出多余的空格。在所有数据的前后,以及两组数据之间不要输出多余的空行。

#include<stdio.h>// summershell
int weihe(long a)//暴力输出,省事简单
{
    int t=0;
    while(a)
    {
        t=t+a%10;
        a/=10;
    }
    return t;
}
int main()
{
    long a[51],i=8899;
    int count=1;
    while(count<20)
    {
        if(weihe(i)%17==0 && weihe(i+1)%17==0)a[count++]=i;
        ++i;
    }
    while(scanf("%d",&count)!=EOF)
        printf("%ld\n",a[count]);
    return 0;
}
           

40 按要求输出序列

作者: 孙辞海 时间限制: 10S 章节: 一维数组

问题描述 :

明明的爸爸是一位著名的数学家。他在明明很小的时候就发现明明有过人的数学天赋,因此有意培养他对数学的兴趣。一次,明明的爸爸为了培养明明对数字的敏感,和明明玩起了一个数字游戏,这个游戏的名称叫“按要求输出序列”。在游戏中,明明的爸爸给了明明一串数字,要求明明首先把这串数字中重复出现的数字删除到仅剩一个,即相同的数字只保留一个,然后将这串数字从小到大进行排序。明明很快就理解了游戏的规则,开始玩起来。明明的爸爸首先给了明明三个数字:3、2、1;明明很快就回答说:“1、2、3”。明明的爸爸惊讶于明明的反应能力,开始加大游戏的难度,给出了由6个数字组成的数字串:2、1、4、3、5、2;明明眼珠子一转,脱口而出:“1、2、3、4、5”(由于“2”出现了两次,因此要删除一个,然后再排序输出。)。明明的爸爸意识到简单的数字串难不住明明,于是决定给出很长的一串数字串来考明明。但与此同时,明明爸爸面对这很长的数字串也无法一时计算出最后的结果,于是就求助于你,让你帮他写一个程序,用来计算出数字串最后的结果。

明明的爸爸的问题可以归结为:给你一个数字串,里面有n个数字,首先对数字串中的数字进行处理,删除重复出现的数字(重复出现的数字只保留一个),然后对数字串从小到大进行排序,最后输出排序后的字符串。

输入说明 :

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据占两行:

第一行是一个正整数n(1≤n≤200),表示数字串中有n个数字,

第二行是n个数字,n个数字都大于等于0且小于等于109,每两个数字用一个空格隔开。

每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明 :

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个排序后的数字串,数字串中的数字用一个空格隔开。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
#include<string.h>
int main()//刚刚那个dp有点费神,这来了个Easy的,赶紧秒了他
{
    int n,temp,a[2020];//我的思路很简单,赋值数组为0,出现就+1
 //   freopen("in.txt","r",stdin);
    while(scanf("%d",&n)!=EOF)
    {
        memset(a,0,sizeof(a));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&temp);
            a[temp]++;
        }
        for(int i=0,c=1;i<2020;i++)//我的小小愿望
            if(a[i])
            printf(c++==1?"%d":" %d",i);
        printf("\n");
    }
    return 0;
}
           

41 部落人乘法

作者: 朱星垠 时间限制: 10S 章节: 一维数组

问题描述 :

明明热爱数学,他的爸爸也有意培养明明对数学的兴趣。

一次,为了拓展明明的知识面,爸爸给明明讲了一个原始部落人计算乘法的方法:

据说原始部落人以小石子作为计算工具,并用减半和加倍两种运算就能求得任何两个整数的乘积。

其规则是:

左边不断除2,写下商,舍去余数;

右边不断加倍,直到左边变成1为止。

取结果的方法是:

如果某行左边是偶数,就划去整个这一行;

如果某行左边是奇数,右边剩下的数相加即可。

例如求13与15的乘积的过程是:

计算过程:

13--------15 :13除以2等于6,舍去余数1,15乘以2等于30;

6---------30 :6除以2等于3,30乘以2等于60;

3---------60 :3除以2等于1,舍去余数1,60乘以2等于120;

1---------120 :左边数字为1,停止计算。

取结果过程:

13--------15 :左边是奇数,取15;

6---------30 :左边是偶数,划去;

3---------60 :取60;

1---------120 :取120;

其结果就是: 13*15=15+60+120=195。

明明对爸爸讲的这个故事相当感兴趣,也自己动手开始模拟上面的过程计算起来。刚开始的时候,明明感觉这样计算很有趣,但是时间一长,明明就觉得这样的计算过程很麻烦。他想让你帮他写一个程序,快速的计算出上述乘法最后相加的式子和结果。

明明的问题可以归结为:给你两个整数,使用上面描述的乘法过程,输出最后的相加的式子。

输入说明 :

你的程序需要从标准输入设备(通常为键盘)中读入多组测试数据。每组测试数据占一行,其中包含两个整数a和b(1 <= a, b <= 100)。

输出说明 :

对每组测试数据,你的程序需要向标准输出设备(通常为启动该程序的终端)依次输出一组对应的答案。格式参见样例。

#include<stdio.h>// summershell
int main()//水题
{
    int a,b;
    while(scanf("%d %d",&a,&b)!=EOF)
    {
        printf("%d*%d=",a,b);
        int c=1,sum=a*b;
        while(a!=1)
        {
            if(a%2==1)printf(c++==1?"%d":"+%d",b);
            a/=2;
            b*=2;
        }
        printf(c++==1?"%d=%d\n":"+%d=%d\n",b,sum);
    }
    return 0;
}
           

42 数列2

作者: frankhuhu 时间限制: 10S 章节: 一维数组

问题描述 :

思维的严密性是相当重要的,尤其是在程序设计中,一个小小的错误,就可能导致无法想象的后果。明明的爸爸是一名富有经验的程序设计专家,深知思维严密的重要性,于是在明明很小的时候,就通过游戏的方式,训练明明的思维严密性。今天,明明的爸爸和明明做了一个数列的游戏。这个游戏很简单,就是有一数列,现在需要在这数列中选出一个或者若干个数(可以不连续),要求这些数的和能被11整除。明明的爸爸想锻炼明明思维的严密性,因此要求明明尽可能多的找出符合条件的数列来,最好一个也不要漏掉。 例如一数列为“11 22 33”,其中11可以被11整除,22可以被11整除,33可以被11整除,11+22=33能被11整除,22+33=55能被11整除,11+33=44能被11整除,11+22+33=66能被11整除。所以以上一数列能被11整除的情况一共有7种。 明明对于这个游戏很感兴趣,高兴地玩了起来。由于粗心,明明总是无法一次就把所有的情况都找出来,这使得他爸爸不是很满意。于是明明爸爸决定先降低游戏的难度,事先告诉明明某一数列总共有多少种符合条件的选择数字的方法,然后再让明明去选。明明的爸爸请你帮一个忙,他不想自己找出所有的情况,因此请你写一个程序,用程序来找出一共有多少种符合选数的情况,并把结果告诉他。

明明爸爸的问题可以归结为:给你一个数列,从中选出1个或若干个数(可以不连续),要求这些数的和能被11整除,问这样的选数方法一共有多少种。

输入说明 :

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据有两行,每组测试数据的第一行有一个整数n(1≤n≤15),表示数列中有多少个整数,每组测试数据的第二行有n个整数,整数的大小都大于等于0且小于等于100,整数之间用一个空格隔开。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明 :

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个整数,即表示一共有多少种选数方法。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。 注:通常,显示屏

#include<stdio.h>// summershell
int main()//嘤嘤嘤,我把36题的答案直接抄过来了,修修补补,AC去!
{//挨个组合,最大约有2^15个组合,还是换个思路吧
    int N,a[32769];//每来一个数就先放进数组,然后挨个位置加和,和放到新的位置上,这样一来,数组需要很大呀
    while(scanf("%d",&N)!=EOF)
    {
        int cou=0,ans=0,temp,len;
        for(int i=0;i<N;i++)
        {
            scanf("%d",&temp);
            a[cou++]=temp;
            len=cou;//把各种组合的加和放进去
            for(int j=0;j<len-1;j++)a[cou++]=a[j]+temp;
        }
        for(int i=0;i<cou;i++)
            if(a[i]%11==0)++ans;
        printf("%d\n",ans);//不知道会不会TLE,好紧张
    }
    return 0;
}
           

43 序列

作者: ZhuKai 时间限制: 2S 章节: 一维数组

问题描述 :

明明的爸爸经常用做游戏的方法启发明明对数学的兴趣。有一次,明明爸爸准备了许多盒子和球,他要和明明做一个放球的游戏。

游戏如下:要将k个小球依次装入到若干个盒子中去(可以使用的盒子数不限)。

小球装入盒子的规则如下:

1)第一个盒子不能为空。

2)依次装入各个盒子的球数必须严格递增。例如:当k=8时,装入方法有1,2,5或1,3,4。

3)装入的盒子数尽可能多。

4)所有相邻盒子的球数之差的绝对值之和最小。

如上例中:装入法1,2,5,则差的绝对值之和为(2-1)+(5-2)=4。装入法1,3,4,则差的绝对值之和为(3-1)+(4-3)=3。因此应该采用后一种装法。

明明明白了规则以后,就兴致盎然地玩起了游戏。起先明明玩得很有劲,每次都能顺利的找出最佳的装小球的方法。但是随着小球数量的增多,装小球的方法也就变得越来越多,明明就需要花更多的时间才能找到最佳的装球方法,这使得明明有些犯难了。于是明明想到了你,他想请你帮他写一个程序,他把小球的数量告诉你,而你的程序用来计算装小球的方法。

明明的问题可以归结为:告诉你小球的数量k,然后通过程序计算出盒子装小球的最佳方法。

输入说明 :

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行有一个整数k(1 ≤k ≤10000),即小球的个数。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明 :

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一串整数,即表示依次放入各个盒子里的小球的个数,每两个数字之间用一个‘,’分隔。每组运算结果单独占一行,其行首和行尾都没有任何空格或其他任何字符,每组运算结果与其后一组运算结果之间没有任何空行或其他任何字符,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行或其他任何字符。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
int main()//由于是严格递增的,所以最低的要求是1 2 3 4 5 6...
{//可以在此基础上,从后往前挨个只放一个数,因为要使其绝对值最小和满足递增
    int k;
    while(scanf("%d",&k)!=EOF)
    {
        int a[2020],i=1,last;
        while(k>=i)
        {
            a[i]=i;
            k-=i;
            i++;
        }
        --i;
        last=i;
        while(k)
        {
            a[i]+=1;
            --k;
            --i;
        }
        for(i=1;i<=last;++i)printf(i==1?"%d":",%d",a[i]);
        printf("\n");
    }
    return 0;
}
           

如果有问题交流咨询,可以加入QQ群:

673852347

44 双重回文数

作者: xxx 时间限制: 1S 章节: 一维数组

问题描述 :

如果一个数从左往右读和从右往左读都是一样,那么这个数就叫做回文数。例如,12321就是一个回文数,而77778就不是。当然,回文数的首和尾都应是非零的,因此0220就不是回文数。事实上,有一些数(如21),在十进制时不是回文数,但在其它进制(如二进制时为10101)时就是回文数。 编一个程序,从文件读入两个十进制数 N (1<= N <= 15) S (0 <S <10000) 然后找出前N个满足大于S且在两种或两种以上进制(二进制至十进制)上是回文数的十进制数,输出到文件上。 本问题的解决方案不需要使用大于4字节的整型变量。

输入说明 :

只有一行,用空格隔开的两个数N和S。

输出说明 :

N行, 每行一个满足上述要求的数,并按从小到大的顺序输出。

#include<stdio.h>// summershell
int judge(int x)//10进制的除X取余倒排法!
{
    if(x==0)return 2;
    int counter=0;
    for(int i=2;i<=10;i++)//2-10进制的判断
    {
        int stack[52],top=-1,temp=x,j;
        while(temp)//换成i进制
        {
            stack[++top]=temp%i;
            temp/=i;
        }
        for(j=0;j<=top/2;j++)
            if(stack[j]!=stack[top-j])break;
        if(j>top/2)counter++;
        if(counter>=2)break;//2种就行了,早点结束
    }
    return counter;
}
int main()
{
    int N,S;
    while(scanf("%d %d",&N,&S)!=EOF)
    {
        int counter=0;
        while(counter<N)
        {
            if(judge(++S)>=2)
            {
                printf("%d\n",S);
                counter++;
            }
        }
    }
    return 0;
}
           

如果有问题交流咨询,可以加入QQ群:

673852347

45 等差数列

作者: xxx 时间限制: 1S 章节: 一维数组

问题描述 :

一个等差数列是一个能表示成a, a+b, a+2b,…, a+nb (n=0,1,2,3,…) 在这个问题中a是一个非负的整数,b是正整数。

写一个程序来找出在双平方数集合S中长度为n的等差数列。双平方数集合是所有能表示成p2+q2的数的集合。

输入说明 :

第一行: N(3<= N<=25),要找的等差数列的长度。 第二行: M(1<= M<=250),搜索双平方数的上界0 <= p,q <= M。

输出说明 :

如果没有找到数列,输出`NONE’。

如果找到了,输出一行或多行, 每行由两个整数组成:a,b 这些行应该先按b排序再按a排序(均为升序)。

将不会有多于10,000个等差数列。

#include<stdio.h>// summershell
#include<stdlib.h>
#include<string.h>//本题的坑,注意pq的范围。
int cmp(const void *a,const void *b)
{
    int x=((int *)a)[1],y=((int *)b)[1];
    if(x!=y)return x-y;
    else return (((int *)a)[0])-(((int *)b)[0]);
}
int main()//由1 5 9 13 17得到规律a..a+4*b,即两个双平方数之间的n个数都是b的整数(整数)倍。就是我们要找的
{
    int n,m,a[62510],ans[10001][2];
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        memset(a,0,sizeof(a));//初始化
        for(int i=0;i<=m;++i)//把所有的双平方数标记出来
        for(int j=0;j<=m;++j)a[i*i+j*j]=1;//注意,上界是m*m*2,一定要小于她,否则0和m*2也可以小于m*m*2且是双平方数
        int c=0;
        for(int i=0,j,k,len;i<=m*m*2;++i)//直接挨个遍历
        {
            if(a[i]==0)continue;//加快判断和检错
            for(j=i+1;j<=m*m*2;++j)//检查i到j之间的n个数是否满足
            {//那么步长b就是(j-i)/(n-1)
                if((j-i)%(n-1)==0)//仅仅整数倍才可以
                {
                    len=(j-i)/(n-1);
                    for(k=1;k<n;++k)
                        if(!a[i+len*k])break;
                    if(k>=n)//查找成功
                    {
                        ans[c][0]=i;
                        ans[c][1]=len;//即是b
                      //  printf("%d %d\n",ans[c][0],ans[c][1]);
                        c++;
                    }
                }
            }
        }
        if(c==0)printf("NONE\n");
        else
        {
            qsort(ans,c,sizeof(ans[0]),cmp);
            for(int i=0;i<c;i++)printf("%d %d\n",ans[i][0],ans[i][1]);
        }
    }
    return 0;
}
           

如果有问题交流咨询,可以加入QQ群:

673852347

46 人见人爱A-B

作者: xxx 时间限制: 1S 章节: 一维数组

问题描述 :

A和B是两个集合,A-B求的是两个集合的差,就是做集合的减法运算。(当然,大家都知道集合的定义,就是同一个集合中不会有两个相同的元素,这里还是提醒大家一下)呵呵,很简单吧?

输入说明 :

输入数据包含T个测试实例。

首先输入数字T,然后输入T组测试数据,每组输入数据占1行,每行数据的开始是2个整数n(0<=n<=100)和m(0<=m<=100),分别表示集合A和集合B的元素个数,然后紧跟着n+m个元素,前面n个元素属于集合A,其余的属于集合B. 每个元素为不超出int范围的整数,元素之间由一个空格隔开.

输出说明 :

针对每组数据输出一行数据,表示A-B的结果,如果结果为空集合,则输出“NULL”,否则从小到大输出结果,为了简化问题,每个元素后面跟一个空格.

#include<stdio.h>// summershell
#include<iostream>
#include<set>//一时set一时爽,一直set一直爽
#include<algorithm>
using namespace std;
int main()
{
    int T,m,n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d",&n,&m);
        set<int>a;
        set<int>b;
        set<int>c;
        set<int>::iterator it;
        for(int i=0,temp;i<n;i++)
        {
            scanf("%d",&temp);
            a.insert(temp);
        }
        for(int i=0,temp;i<m;i++)
        {
            scanf("%d",&temp);
            b.insert(temp);
        }
      set_difference(a.begin(),a.end(),b.begin(),b.end(),inserter(c,c.begin()));
        if(c.empty())printf("NULL");
        else for(it=c.begin();it!=c.end();it++)printf("%d ",*it);
        printf("\n");
    }
    return 0;
}
           

如果有问题交流咨询,可以加入QQ群:

673852347

47 最少拦截系统

作者: xxx 时间限制: 1S 章节: 一维数组

问题描述 :

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能达到前一发的高度。

某天,雷达捕捉到敌国的导弹来袭,如果系统数量太少,将导致有可能不能拦截所有的导弹。所以,根据雷达捕捉到的导弹高度,需要预先准备相应数量的拦截系统。

比如导弹的高度依次为:

5 3 4 2 4 1

则一个拦截系统的第一发炮弹必须打到高度5的地方,第二发炮弹打到高度3的地方。

但第三发炮弹打不到高度4的地方(因为每一发炮弹不能达到前一发的高度),所以要使用第二套拦截系统。

第二套拦截系统发射的炮弹高度打到4和2的高度(实际上,要拦截高度为2的炮弹,使用第一套拦截系统或者第二套都可以),

第三套拦截系统发射的炮弹高度打到4和1的高度(实际上,要拦截高度为1的炮弹,三套拦截系统都可以)。

因此,总共需要三套拦截系统。

再比如导弹的高度依次为:

5 3 4 2 3 1

则一个拦截系统的第一发炮弹必须打到高度5的地方,第二发炮弹打到高度3的地方。

但第三发炮弹打不到高度4的地方(因为每一发炮弹不能达到前一发的高度),所以要使用第二套拦截系统。

第二套拦截系统发射的炮弹高度打到4的高度。

再要拦截高度为2的炮弹,使用第一套拦截系统或者第二套都可以,但考虑到后面还需要拦截炮弹,我们这里使用第一套拦截系统(为什么不能用第二套,自己想啦)。

再要拦截高度为3的炮弹,我们使用第二套拦截系统。

再拦截高度为1的炮弹,第一套和第二套系统都可以,我们就使用第二套吧。

因此,总共仅需要两套拦截系统,第一套拦截的是5 3 2,第二套拦截的是4 3 1。

请根据给定的高度数据,帮助计算一下最少需要多少套拦截系统。

输入说明 :

输入数据首先包括一个整数T (1<=T<= 100),,表示测试数据的组数。

每组测试数据的第一行是一个整数N(1<= N <= 1000),代表着导弹总个数(正整数), 接下来用N个数字代表着导弹依次飞来的高度,其中雷达给出的高度数据是不大于10000的正整数,用空格分隔。

输出说明 :

对应每组数据输出拦截所有导弹最少要配备多少套这种导弹拦截系统。

每组输出占一行,行首与行尾无空格。

#include<stdio.h>// summershell
int main()//注意一点,同一系统中以后的每个导弹都没有前面的高,即使隔了几套系统再发射也是
{//这题意掌握住,这道题就很轻松了,在数组中存放每个系统的高度,每使用一次就降低一次高度
    int T,n,missile[2020],cou,temp,proper;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d",&n,&missile[0]);
        cou=1;
        for(int i=1;i<n;++i)
        {
            scanf("%d",&temp);
            proper=-1;
            for(int j=0,c=0;j<cou;j++)//每次都用较高值去拦截,不至于浪费
            {
                if(temp<missile[j])
                {
                    if(c++==0)proper=j;
                    else if(missile[proper]>missile[j])proper=j;
                }
            }
            if(proper==-1)//如果没找到合适的那就开辟一个新的系统
                missile[cou++]=temp;
            else missile[proper]=temp;
        }
        printf("%d\n",cou);
    }
    return 0;
}
           

如果有问题交流咨询,可以加入QQ群:

673852347

48 求N!

作者: xxx 时间限制: 1S 章节: 一维数组

问题描述 :

给你一个整数N(0 ≤ N ≤ 10000),你的任务是计算并输出 N!

输入说明 :

输入多行,每行一个N。

输出说明 :

对于每个输入N,在一行中输出N!

行首与行尾为空格,两组输出之间无空行。

#include<stdio.h>// summershell
void fun(int N)//利用数组来实现大数的进位
{
    int a[100001],len=1;
    for(int i=0;i<100001;i++)a[i]=0;
    a[1]=1;
    for(int i=2,j;i<=N;i++)
    {
        int temp=0;//temp是中间的暂时变量
        for(j=1;j<=len;j++)
        {
            temp=(temp+a[j]*i);
            a[j]=temp%10;
            temp=temp/10;
        }
        while(temp){a[j++]=temp%10;temp/=10;len++;}//乘数是多位的进位比较麻烦
    }
    for(int i=len;i>0;--i)printf("%d",a[i]);
    printf("\n");
}

int main()
{
    int N;
    while(scanf("%d",&N)!=EOF)fun(N);
    return 0;
}
           

49 我素故我在

作者: xxx 时间限制: 1S 章节: 深度优先搜索

问题描述 :

有这样一种素数叫纯素数(YY出来的名字),当它是一个多位数的时候,你把它的末位去掉之后余下的数依然是一个素数。比如说2393,2393 本身是一个素数,它的末位去掉之后,余下的是239。239 是一个素数,它的末位去掉之后,余下的是23 。23是一个素数,它的末位去掉之后,余下的是2 。2依然还是一个素数。纯素数的长度叫做“维”。2393 是一个4维素数。3797也是一个4维素数。

输入说明 :

第一行先给出一共有多少组数据N(N<=1000),接下来有N组数据.

每组包括一个整数T(1<=T<=8)。

输出说明 :

按照从小到大的顺序输出所有的T维纯素数。

#include<stdio.h>// summershell
#include<math.h>//本来想打表8位来着运行CPU卡爆了,再看题目提示深度优先搜索
#include<string.h>
int is_prime(int a)
{
    if(a<2)return 0;
    if(a==2)return 1;
    for(int i=2,sq=sqrt(a);i<=sq;i++)
        if(a%i==0)return 0;
    return 1;
}
int num[10][101];//从单位素数开始,逐渐增加维数。行数代表有几位。
int dfs(int a,int div)//num[0]存储有几个素数了。i是维度
{
    if(div>8)return 0;
    num[div][0]++;
    num[div][num[div][0]]=a;
    for(int i=0;i<10;i++)
    {
        if(is_prime(a*10+i))dfs(a*10+i,div+1);
    }
    return 1;
}
int main()
{
    int T,N;
    memset(num,0,sizeof(num));
    dfs(2,1);//一开始只对个位数下手,慢慢往上加
    dfs(3,1);
    dfs(5,1);
    dfs(7,1);
    scanf("%d",&N);
    while(N--)
    {
        scanf("%d",&T);
        for(int i=1;i<=num[T][0];i++)printf("%d\n",num[T][i]);
    }
    return 0;
}
           

如果有问题交流咨询,可以加入QQ群:

673852347

50 素数

作者: frankhuhu 时间限制: 3S 章节: 函数

问题描述 :

明明的爸爸是一位数学家,明明受他爸爸的影响从小就喜欢数学,经常向他爸爸学习或请教数学问题。一天,明明问他爸爸什么是素数,明明的爸爸回答说:“首先,素数都是大于1的自然数;其次,素数是只能被1和其本身整除的数。例如‘3’这个数,它只能被1和3这两个整数整除,因此‘3’就是素数;但是‘4’就不是素数,因为4除了能被1和4整除外,还能被2整除,因此‘4’就不是一个素数。”明明对于爸爸的回答很满意,也很快明白了素数的定义。于是明明的爸爸就问明明:“明明,你现在知道了什么是素数,那我现在给你一个整数区间,你能告诉我在这个区间里,一共有多少个素数吗?” 例如:一个区间为[1,10],则在这个区间里一共有2、3、5、7,总共4个素数。 明明想了想,觉得这很简单,就说:“没问题。”于是明明爸爸就给了明明一个很大的区间,这下明明有点犯难了,由于区间太大,一个一个算过了会很花时间。聪明的明明想到了你,你总是乐于助人。明明想让你帮他写一个程序,用来计算在某一个整数区间内一共有多少个素数。 明明的问题可以归结为:给你一个整数区间,求出在这个区间里共有多少个素数。

输入说明 :

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅有一行,每组测试数据有两个正整数M,N(0 < M ≤ N ≤ 1000000),表示一个整数区间。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明 :

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个整数,即区间[M, N]内一共有多少个素数。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
#include<string.h>//counter表示0到i之间有几个素数
int prime[1000001],counter[10000000];//QVQ打表一时爽,一直打表一直爽!
void find_prime()
{
    memset(prime,0,sizeof(prime));//0代表是素数,1代表不是
    prime[0]=prime[1]=1,counter[0]=counter[1]=0;
    for(int i=2;i<1000001;i++)
        if(prime[i]==0)
        {
            counter[i]=counter[i-1]+1;
            for(int j=i+i;j<1000001;j+=i)
                prime[j]=1;
        }
        else
            counter[i]=counter[i-1];
}
int main()
{
    int N,M;
    find_prime();
    while(scanf("%d %d",&M,&N)!=EOF)
    {
        printf("%d\n",prime[M]?counter[N]-counter[M]:counter[N]-counter[M]+1);//作差即是区间内的个数
    }
    return 0;
}
           

51 歌德巴赫猜想

作者: z sj 时间限制: 2S 章节: 函数

问题描述 :

歌德巴赫猜想指出:任何一个大于2的偶数,都可以表示成两个素数的和。例如:8 = 3+5, 44 = 13+31等。试编程在6至100范围内验证歌德巴赫猜想。

输入说明 :

先输入一个正整数n,表示有n组测试数据。所有数据前后没有多余的空行,两组数据之间也没有多余的空行。每组输入数据由一行组成,在接下来的n行中,每行有1个偶数a(6≤a≤100),在行首和行尾没有多余的空格。

输出说明 :

对于每组输入,输出满足歌德巴赫猜想两个素数,小的素数的在前,在行首和行尾没有多余的空格。如果有多组结果,输出的第一个素数要求最小。所有数据前后没有多余的空行,两组数据之间也没有多余的空行。

#include<stdio.h>// summershell
int pri[510];
void prime()
{
    for(int i=0;i<510;i++)pri[i]=1;
    pri[0]=pri[1]=0;
    for(int i=2;i<510;i++)
        if(pri[i])
            for(int j=i+i;j<510;j+=i)
                pri[j]=0;
}
int main()//So easy!
{
    int N,temp;
    prime();
    while(scanf("%d",&N)!=EOF)
    {
        while(N--)
        {
            scanf("%d",&temp);
            for(int i=1;i<510;++i)
                if(pri[i]==1 && pri[temp-i]==1)
                {
                    printf("%d %d\n",i,temp-i);
                    break;
                }
        }
    }
    return 0;
}
           

52 N的倍数

作者: 张志寿 时间限制: 2S 章节: 函数

问题描述 :

明明的爸爸在研究一个复杂的数学问题,研究了很长时间都没有结果。明明看见后就问爸爸在研究什么。明明的爸爸回答说:“我在研究一个整数的倍数问题,想找到某个数的倍数……”明明还没有等他爸爸说完,就抢着说:“这不是很简单嘛,你把这个整数乘以1,乘以2,……,就能得到很多的倍数呀。”明明的爸爸当然知道这种方法,但是他接着说:“这样的方法找倍数当然容易,但是我找的倍数有一个特点,那个倍数只能由0或1组成,且应该尽量的小。例如一个自然数2,它符合要求的那个倍数就是10。”这下明明明白为什么爸爸研究了那么多时间都还没有研究出结果了,因为随着数字的增大,找到它的符合要求的倍数越来越难。明明想帮他爸爸解决这个问题,于是他来求助于你,能否帮他爸爸写一个程序,来求一个整数的倍数,倍数仅有0或1组成,且要尽可能小。 明明的问题可以归结为:任意给定一个自然数N,寻找一个M,要求M是N的倍数,且它的所有各位数字都是由0或1组成,并要求M尽可能小。

输入说明 :

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行仅包括一个正整数N(1≤N≤100),代表要求倍数的那个整数。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明 :

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个整数,即N的倍数M。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
int main()//不妨把哪些简单的倍数都枚举出来
{
    int k,c=7;
    int a[2020]={1,10,11,100,101,110,111};//规律是*10+0/1
    for(int i=3;i<2020 && c<2020;i++)
    {
        a[c++]=a[i]*10;
        a[c++]=a[i]*10+1;
    }
    while(scanf("%d",&k)!=EOF)
    {
        for(int i=0;i<2020;i++)
            if(a[i]%k==0)
            {
                printf("%d\n",a[i]);
                break;
            }
    }
    return 0;
}
           

53 求n天后的日期

作者: Turbo 时间限制: 2S 章节: 函数

问题描述 :

写一个函数,传入年月日,计算它的第二天,并返回该日期。由用户输入年月日和一个n值,使用前述函数,计算该日期加n天的日期为多少。

输入说明 :

输入year,month,day和n共4个正整数,以空格分隔。n的值不超过2000。

输出说明 :

输出计算得到的结果年月日共3个正整数,整数之间以一个空格分隔,行首与行尾无多余空格。

#include<stdio.h>// summershell
int main()
{
    int y,m,d,n;
    int month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    scanf("%d %d %d %d",&y,&m,&d,&n);
    while(n)
    {
        if((y%400==0)||(y%100!=0 && y%4==0))month[2]=29;
        else month[2]=28;
        d++;
        n--;
        if(d>month[m]){m++;d=1;}
        if(m>12){y++;m=1;}
    }
    printf("%d %d %d\n",y,m,d);
    return 0;
}
           

54 菱形输出

作者: 孙辞海 时间限制: 1S 章节: 函数

问题描述 :

明明这次又碰到问题了:

给定一个正整数N,明明的爸爸让他输出一个以Z开始的菱形,以后依次为Y,X…,

比如当N等于1的时候输出图形:

Z

当N等于2的时候,输出图形:(Y前没有空格,Z、X和W前一个空格)

Z

Y X

W

当N等于3的时候,输出图形:

Z

Y X

W V

U T

S

明明发现当N很大的时候就不是很容易了,所以找到了你,希望你编写一个程序帮助他

明明的问题可以归结为:输入一个正整数N,输出一个以Z开始的菱形,以后依次为Y,X…。

输入说明 :

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行仅包括一个正整数n(1≤n≤7)。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明 :

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组输出一个以Z开始的菱形,具体格式参照样例输出。每组运算结果与其后一组运算结果之间有一个空行,最后一组运算结果之后没有空行。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
int main()//题目n=2时候的图形是不是错了?那不是个菱形啊
{
    int n,num=1;
    while(scanf("%d",&n)!=EOF)
    {
        if(num++!=1)printf("\n");
        int c=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n+i-1;++j)
            {
                if(j==n-i+1 || j==n+i-1)printf("%c",'Z'-c++);
                else printf(" ");
            }
            printf("\n");
        }
        for(int i=n-1;i>0;i--)
        {
            for(int j=1;j<=n+i-1;++j)
            {
                if(j==n-i+1 || j==n+i-1)printf("%c",'Z'-c++);
                else printf(" ");
            }
            printf("\n");
        }
    }
    return 0;
}
           

55 三角形的个数

作者: 朱凯 时间限制: 10S 章节: 函数

问题描述 :

明明的爸爸常用玩游戏的方法来激发明明对几何学的兴趣。这天明明的爸爸和明明又玩起了有关三角形的游戏。

明明爸爸对明明说:“我们能不能构造一个周长为15的三角形?” “太简单了,”明明说道:“三条边长都是5的三角形,它的周长不就是15吗?” “明明真聪明,算得真快。”明明爸爸接着说:“可是,我不想要三条边都相等的三角形哪!” 明明大眼睛一转,说道:“那也好办啊,我只要对这个等边三角形的一条边减去一个数,再把这个数加到另一条边上就可以得到一个新的周长为15的三角形。例如,在第一条边上减去1,在第二条边上加上1,这样不就可以得到一个周长为15的新的三角形了吗?” “哇,明明太聪明了”爸爸称赞道。“对,如果把第一条边上减去的1加到第三条边上去不就又可以得到周长为15的另外一个新三角形了吗?”爸爸模仿着明明的方法和语气。 “不对呀,爸爸。你构造的三角形和我构造的三角形是同样的三角形。爸爸你看,我的三角形三条边分别长为4、6、5,而你的三角形三条边分别长为4、5、6,将三条边按其边长排序后都得到4、5、6,所以它们是同一个三角形,不是两个不同的三角形。” “啊,还是明明聪明。那还有没有其他周长为15的三角形吗?” “当然有啦。三条边边长分别为4、4、7的三角形,它的周长就是15,不过你可能不喜欢它,因为它有两条边的边长相等。” 明明和爸爸玩了一下午这样的三角形游戏,明明一共又构造了另外两个他认为他爸爸喜欢的三角形,即边长分别为2、6、7的三角形和边长分别为3、5、7的三角形。

晚上,明明躺在床上还在思考:如果周长不是15,而是90,那么爸爸喜欢的三角形有多少个呢?

明明的问题可以归结为:根据一个正整数n(3 ≤ n ≤ 100),要求统计出同时满足下列条件的三角形的个数:

  1. 边长都是整数。
  2. 周长为n。
  3. 边长两两不相等。

    之所以有上述第一个条件,那是因为明明只知道正整数,没有学过分数和实数,因此他构造出的三角形的边长均为正整数。 请你写一个程序来帮助明明计算出他认为他爸爸喜欢的三角形的个数。

    输入说明 :

    你写的程序需要从标准输入设备(通常为键盘)中读入多组测试数据,每组测试数据仅占一行,每行仅包括一个正整数n(3 ≤ n ≤ 100),代表需要被统计的三角形的周长,n的前后都没有任何空格。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

    输出说明 :

    对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果依次写入到标准输出设备(通常为启动该程序的文本终端,例如Windows中的命令行终端)中。每组运算结果为一个大于等于0的整数构成,即满足条件的三角形的个数。例如:测试数据n为15时,运算结果应为3。输出时,每组运算结果占一行,其行首和行尾都没有任何空格或其他字符,每组运算结果与其后一组运算结果之间没有任何空行或其他字符,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行或其他字符。

#include<stdio.h>// summershell
#include<cmath>
int sanjiao(int a,int b,int c)//判断是否为三角形 a<b<c
{
    if(a+b>c && std::abs(b-a)<c)return 1;
    else return 0;
}
int main()//Easy!
{
    int n,a,b,c;
    while(scanf("%d",&n)!=EOF)
    {
        int cou=0;
        for(int i=1;i<n/2;i++)
        {
            for(int j=i+1;j<n/2;++j)
            {
                a=i;b=j;c=n-i-j;
                if(b>=c)break;//保证不会重复
                if(sanjiao(a,b,c)&&sanjiao(a,c,b)&&sanjiao(c,b,a))cou++;
            }
        }
        printf("%d\n",cou);
    }
    return 0;
}
           

56 汉诺塔问题的第m步

作者: Turbo 时间限制: 3S 章节: 递归

问题描述 :

给定三根杆A、B、C和大小不同的几个盘子。这些盘子按尺寸递减顺序套在A杆上,最小的在最上面。现在的任务是把这些盘子从A杆移到C杆且保持原来堆放顺序。在实现任务时,每次只能移动一个盘子,且任何时刻不允许大的盘子放在小的盘子上面,B杆可以作为辅助存放杆。求:总共有n个圆盘时,搬动过程中的第m步是从哪个杆到哪个杆。

输入说明 :

你的程序需要从标准输入设备(通常为键盘)中读入多组测试数据。每组输入数据由一行组成,每行输入一个整数表示盘子数n,1≤n≤10,以及步数m,两个数据之间以一个空格分隔。行首和行尾没有多余的空格,两组数据之间也没有多余的空行。

输出说明 :

对每组测试数据,你的程序需要向标准输出设备(通常为启动该程序的终端)依次输出一行对应的答案,该行中输出第m步移动的情况,如第m步是从A移到B,则输出“A–B”(不包括引号)。如果移动过程不存在第m步,则输出“none” (不包括引号)。

两组数据之间无空行,第一组前及最后一组后也无空行。

#include<stdio.h>// summershell
int counter,m,flag;
void movepan(char A,char B)
{
    counter++;
    if(counter==m){printf("%c--%c\n",A,B);flag=1;}
}
void hannio(int n,char A,char C,char B)//定义,从A移动到C盘,以B为辅助
{
    if(n==1)movepan(A,C);
    else
    {
        hannio(n-1,A,B,C);
        movepan(A,C);
        hannio(n-1,B,C,A);
    }
}
int main()//C程序设计里面的经典问题
{
    int n;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        counter=0;flag=0;
        hannio(n,'A','C','B');
        if(flag==0)printf("none\n");
    }
    return 0;
}
           

57 数字游戏

作者: xxx 时间限制: 1S 章节: 递归

问题描述 :

现在,有许多给小孩子玩的数字游戏,这些游戏玩起来简单,但要创造一个就不是那么容易的了。 在这,我们将介绍一种有趣的游戏。

你将会得到N个正整数,你可以将一个整数接在另一个整数之后以制造一个更大的整数。 例如,这有4个数字123, 124, 56, 90,他们可以制造下列整数─ 1231245690, 1241235690, 5612312490, 9012312456, 9056124123…等,总共可以组合出24(4!)种数字。 但是,9056124123是最大的那一个。

你可能会想这是个简单的事情,但对刚有数字概念小孩来说,这会是个简单的任务吗?

输入说明 :

输入含有多组测试数据。

每组测试资料两行,第一行为一个正整数N(N<= 50),第二行将有N 个正整数。

当N=0代表输入结束。

输出说明 :

对每一组测试数据,输出一行,输出利用这N个整数可结合成的最大整数。

我的AC代码:

#include<stdio.h>// summershell
#include<stdlib.h>
#include<string.h>//标了一个"难"字。还有递归,第一感觉是字符串比较然后排序,但是做了一下发现,如果首字母相同,比较起来会出现问题,990和99,明显99990比99099好。所以换一种思路去排序,就是还要满足99099和990的。直接比较连接之后的大小。因为,这样的比较是相对的,就是可以往两字符串中间插入其他相同的字符串,还是一个最优的结果。可以这样排序。例如99099990>99099099,那么99099X990>990X99099。其中X为任意字符串
int cmp(const void *a,const void *b)
{
    char *s1=(char *)a,*s2=(char *)b,x[100],y[100];
    strcpy(x,(char *)a);
    strcpy(y,(char *)b);
    strcat(x,s2),strcat(y,s1);
    return strcmp(y,x);
}
int main()//
{
    int n;
    char s[50][50];
    while(scanf("%d",&n)!=EOF && n)
    {
        for(int i=0;i<n;++i)
            scanf("%s",s[i]);
        qsort(s,n,sizeof(s[0]),cmp);
        for(int i=0;i<n;++i)printf("%s",s[i]);
        printf("\n");
    }
    return 0;
}
           

58 矩阵转换

作者: ZhouMingLiang 时间限制: 1S 章节: 二维数组

问题描述 :

明明是一个很聪明的孩子,学什么东西都很快。但是他也有个缺点,就是不愿意做重复的劳动,往往学会一样东西以后,就不太愿意再去碰它。有一天,明明在数学课上学了矩阵的转换,即有一个r×r的矩阵,把矩阵中的数以左上到右下的对角线的方式进行交换,然后形成一个新的矩阵。

例如:有个3×3的矩阵如下:

1 2 3

4 5 6

7 8 9

通过以左上到右下的对角线交换后,形成了一个新的矩阵:

1 4 7

2 5 8

3 6 9

明明很快就学会了,然后自己动手做了几个类似的转换。但是,课后老师布置了很多矩阵转换的作业,让同学回家练习,这就使明明很厌烦了,觉得自己已经学会了,就没有再练习的必要了。于是明明就请你帮个忙,帮他写一个程序,来计算矩阵的交换,帮他完成老师布置的作业。

明明的问题可以归结为:有一个r×r的矩阵,把矩阵中的数以左上到右下的对角线的方式进行转换,然后输出转换后的矩阵。

输入说明 :

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据有多行,每组测试数据的第一行有一个整数r(1≤r≤10),表示一个r×r的矩阵,接下来有r行,每行有r个整数,表示要转换的矩阵中的数,每个数用一个空格隔开。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明 :

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个转换后的矩阵。每组运算结果形成r行数据,每一行的数字之间以一个空格分隔,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间有一个空行,最后一组运算结果后面没有空行。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
int main()//Easy!
{
    int r,c=1,a[20][20];
    while(scanf("%d",&r)!=EOF)
    {
        if(c++!=1)printf("\n");
        for(int i=1;i<=r;i++)
            for(int j=1;j<=r;j++)
            scanf("%d",&a[i][j]);
        for(int i=1;i<=r;i++)
        {
            for(int j=1;j<=r;j++)
            printf(j==1?"%d":" %d",a[j][i]);
            printf("\n");
        }
    }
    return 0;
}
           

59 魔方阵

作者: SunCiHai 时间限制: 1S 章节: 二维数组

问题描述 :

在一次数学课上,明明的老师讲了一种非常有趣的方阵,称之为三阶魔方阵。

它是一个三行三列,由1、2、3、……8、9,九个数字共同构成,且它每行、每列、两对角线之和均相等,于是一个合法的三阶魔方阵就形成了以下的方阵:

8 1 6

3 5 7

4 9 2

富有钻研精神的明明回家后,马上就对三阶魔方阵进行研究。

他总结出了5条n阶魔方阵的规律(n为奇数),如下:

(1) 将“1”放在第一行(最上面一行)中间一列;

(2) 从“2”开始直到n*n为止各数依次按下列规则存放:每一个数存放的行的行数比前一个数的行数减1,每一个数存放的列的列数比前一个数的列数加1,即前一个数的右上方。

(3) 如果上一数的行数为1,则下一个数的行数为n(指最下面一行);

(4) 当上一个数的列数为n时,下一个数的列数应为1(指最左一列);

(5) 如果按上面规则确定的位置上已有数,或上一个数是第一行第n列时,则把下一个数放在上一个数的下面。

有了以上的方法,明明就可以轻易地构造出任意的n阶魔方阵。

例如构造3阶魔方阵的过程如下:

先将1放在第一行的中间一列:
放1:(参考规则1)
* 1 *
* * *
* * *
放2:(参考规则3)
* 1 *
* * *
* * 2
放3:(参考规则4)
* 1 *
3 * *
* * 2
放4:(参考规则5)
* 1 *
3 * *
4 * 2
放5:(参考规则2)
* 1 *
3 5 *
4 * 2
放6:(参考规则2)
* 1 6
3 5 *
4 * 2
放7:(参考规则5)
* 1 6
3 5 7
4 * 2
放8:(参考规则4)
8 1 6
3 5 7
4 * 2
放9:(参考规则3)
8 1 6
3 5 7
4 9 2
           

但是随着n的不断增大,构建一个n阶魔方阵所花的精力就越多。于是明明就请你帮忙,帮助他用程序来构建n阶魔方阵。

明明的问题可以归结为:给你一个阶数n,请你按照题目中描述的方法,构造出n阶魔方阵。

输入说明 :

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行仅包括一个正整数n(1≤n≤19,且n是奇数),表示要构造的魔方阵阶数。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明 :

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。输出时,每组运算结果为n阶魔方阵。每组运算结果与其后一组运算结果之间有一个空行,最后一组运算结果后面没有空行。 注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
int main()//幸好题目给了规则,不然这规律难搞哦!
{//模板还是上一题的,直接写
    int n,c=1,a[20][20];
    while(scanf("%d",&n)!=EOF)
    {
        if(c++!=1)printf("\n");
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)a[i][j]=0;
        a[0][n/2]=1;
        int lastrow=0,lastcolumn=n/2;//比较模除运算方便
        for(int i=2;i<=n*n;++i)
        {
            int temprow=(lastrow-1+n)%n,tempcolumn=(lastcolumn+1)%n;
            if((lastrow==0&&lastcolumn==n-1) ||(a[temprow][tempcolumn]!=0) )
            {
                lastrow++;
            }
            else
            {
                lastcolumn=tempcolumn;
                lastrow=temprow;
            }
            a[lastrow][lastcolumn]=i;
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            printf(j==0?"%d":" %d",a[i][j]);
            printf("\n");
        }
    }
    return 0;
}
           

如果有问题交流咨询,可以加入QQ群:

673852347

60 最大效益

作者: 朱星垠 时间限制: 10S 章节: 二维数组

问题描述 :

明明的爸爸开了一家小公司,公司里有5名职员。今天,公司接待了5位客户。明明的爸爸知道,和任何一位客户谈判并签下合同都要花一整天的时间,而他又希望在一天之内,和这5位客户都签好合同。因此,明明的爸爸要求公司里的5名职员分别与1位客户谈判。

明明的爸爸也知道,这5名职员和5位客户的性格各不相同。因此,不同的职员与不同的客户谈判,会给公司带来不同的经济效益。他现在要做出一个决策,让5名职员分别与哪位客户谈判,才能让公司今天的总经济效益最大。

明明的爸爸首先做了一张5行5列的效益表,如下所示:

1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
           

在这张效益表中,每行代表一名公司职员,每列代表一个客户,每行中的5个数字就表示了当该行所代表的公司职员和每位客户谈判时所能产生的效益。明明的爸爸就要通过这张效益表来决定哪位职员与哪位顾客谈判,然后能够使公司的效益最大。就拿上面这张表来看,由于无论哪位职员与哪位客户谈判,所产生的效益都是1,因此最大的效益就是5。这是最简单的一种情况,但是当效益表里的数字变得复杂,就很难进行选择,到底哪种组合方式才是最优的。因此明明的爸爸求助于你,帮助他解决这个问题。

明明的爸爸的问题可以归结为:给你一张5行5列的效益表,表中的数字均为大于等于0的整数,要求在这张表中选出5个数字,使这5个数字的和最大。(注:这5个数字分别来自表中的不同行不同列,即同一行只能选择一个数字,同一列也只能选择一个数字。)

输入说明 :

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据。每组测试数据占5行;每行包含5个正整数;第i行的第j个正整数Aij代表第i名职员与第j位客户谈判能为公司带来的经济效益(0≤Aij≤100, 1≤i,j≤5)。每组测试数据与其后一组测试数据之间没有任何空行;第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明 :

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个整数s,即这一天中公司的最大可能总经济效益。例如:当测试数据中的所有Aij(1≤i,j≤5)均为1时,运算结果s应为5。输出时,每组运算结果s单独占一行,其行首和行尾都没有任何空格或其他任何字符;每组运算结果与其后一组运算结果之间没有任何空行或其他任何字符,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行或其他任何字符。

注:通常,显示屏为标准输出设备。

#include<stdio.h>// summershell
int a[6][6],maxnum,visit[6],result[6];
void pailie(int level,int n)
{
    if(level>n+1)return;
    if(level==n+1)
    {
        int temp=0;
        for(int i=1;i<=n;i++)temp+=a[i][result[i]];
        if(temp>maxnum)maxnum=temp;
        return;
    }
    for(int i=1;i<=n;i++)
    {
        if(visit[i]==0)
        {
            visit[i]=1;
            result[level]=i;//敲定当前的排列值
            pailie(level+1,n);
            visit[i]=0;
        }
    }
}
int main()//我觉得难度是有的,关于排列的实现吧
{

    while(scanf("%d %d %d %d %d",&a[1][1],&a[1][2],&a[1][3],&a[1][4],&a[1][5])!=EOF)
    {
        for(int i=2;i<=5;i++)
            for(int j=1;j<=5;j++)scanf("%d",&a[i][j]);
        maxnum=-100;
        for(int i=0;i<6;i++)visit[i]=0;
        pailie(1,5);
        printf("%d\n",maxnum);
    }
    return 0;
}
           

如果有问题交流咨询,可以加入QQ群:

673852347