基础算法训练
一:一个月的天数
问题描述 :
输入年和月,输出该月有几天。
输入说明 :
输入两个整数,中间以空格分隔,第一个整数表示年,第二个整数表示月。
输出说明 :
输出该年该月的天数,输出时,行首与行尾均无空格,仅输出一个整数。
输入范例 :
2000 2
输出范例 :
29
#include<iostream>
using namespace std;
int main(){
int year,month;
scanf("%d%d",&year,&month);
if(year%4==0&&year%100!=0||year%400==0 && month==2)
printf("29\n");
else if(month==2)
printf("28\n");
else if(month==1||month==3||month==5||
month==7||month==8||month==10||month==12)
printf("31\n");
else printf("30\n");
return 0;
}
二:银行存款到期日
银行存款有3个月、6个月定期等。从键盘输入一个日期(即为存款日期)以及定期的时间长度(单位为月,输入的时间长度可为小于等于60的任意正整数),请编程输出该定期存款的到期日期。 下面以3个月定期为例,说明定期的概念。
比如:
输入2014年4月30日,则到期日是2014年7月30日;
输入2014年3月31日,则到期日是2014年6月30日(6月没有31日,所以30日就到期);
输入2014年11月30日,则到期日是2015年2月28日;
输入2015年11月30日,则到期日是2016年2月29日。
输入说明 :
共输入4个整数,中间以空格分隔,第一个整数表示年,第二个整数表示月,第三个整数表示日,第四个整数表示定期长度(单位为月)。
输出说明 :
输出到期日期,共输出三个整数,中间以一个空格分隔,行首与行尾均无空格。
#include<stdio.h>
int run(int year)//闰年判断
{
if((year%4==0&&year%100!=0)||year%400==0)
return 1;
else
return 0;
}
int main()
{
int year,month,date,regular,yearresult,monthresult,dateresult;
//输入年月日期限,输出年月日
scanf("%d%d%d%d",&year,&month,&date,®ular);
yearresult = year;//对输出年数进行默认值赋值
while(month+regular>12)//如果存储到期不在本年,则需要计算到期年份
{
yearresult++;
regular-=12;//每12个月为一年,同时更新yearresult的值
}
monthresult = (month+regular)%12;//计算到期月份
if(monthresult==0) monthresult=12;//易错
if(monthresult==2&&date>=29)//考虑闰年2月情况
{
if(run(yearresult))dateresult=29;
else dateresult=28;
}
//考虑小月遇到31号
else if((monthresult==4||monthresult==6||monthresult==9||monthresult==11)&&date==31)
{
dateresult=30;
}
else
{
dateresult=date;
}
printf("%d %d %d\n",yearresult,monthresult,dateresult);
return 0;
}
三:解二次方程
编写程序求方程ax2+bx+c=0的根,a、b、c的值由键盘输入,假设b2-4ac>0
输入说明 :
3个整数a b c,以一个空格分隔
输出说明 :
两个根,大数在前,小数在后
输出时保留两位小数。
#include<stdio.h>
#include<math.h>
int main()
{
int a,b,c;
double gen1,gen2;
scanf("%d%d%d",&a,&b,&c);
gen1 = (-b+sqrt(b*b-4*a*c))/(2*a);
gen2 = (-b-sqrt(b*b-4*a*c))/(2*a);
printf("%.2f %.2f",gen1,gen2);
return 0;
}
四:时间相加
输入两个时间A和B,分别都由3个整数组成,分别表示时分秒,比如,假设A为34 45 56,就表示A所表示的时间是34小时 45分钟 56秒。
输出A+B即两个时间相加后的结果。
输入说明 :
输入数据由6个整数AH,AM,AS,BH,BM,BS组成,分别表示时间A和B所对应的时分秒。题目保证所有的数据合法。
输出说明 :
输出A+B,输出结果也由时分秒三部分组成,同时也要满足时间的规则(即:分和秒的取值范围在0~59),输出仅占一行,整数之间以一个空格分隔,行首与行尾无多余空格。
#include<stdio.h>
int main()
{
int AH,AM,AS,BH,BM,BS,hab,mab,sab;//hab,mab,sab分别为相加后的结果
int p1=0,p2=0;//p1,p2作为进位
scanf("%d%d%d%d%d%d",&AH,&AM,&AS,&BH,&BM,&BS);
sab=AS+BS;
while(sab>=60)//超过60就进一位,即p的值加1
{
p1++;
sab-=60;
}
mab=AM+BM+p1;
while(mab>=60)
{
mab-=60;
p2++;
}
hab=AH+BH+p2;
printf("%d %d %d\n",hab,mab,sab);
return 0;
}
五:求第几天
按年、月、日的顺序读入一个日期,输出该日期是这一年中的第几天。
输入说明 :
输入数据为三个正整数y 、m、d,分别表示年、月、日,整数之间以空格分隔,在行首和行尾没有多余的空格。
输出说明 :
输出一个整数,表示输入的日期是这一年中的第几天,在行首和行尾没有多余的空格。
#include<stdio.h>
int isrun(int n)//闰年判断
{
if((n%4==0&&n%100!=0)||n%400==0) return 1;
else return 0;
}
int main()
{
int i,sum=0;
int a[12]={31,28,31,30,31,30,31,31,30,31,30,31};//非闰年每月天数
int y,m,d;
scanf("%d%d%d",&y,&m,&d);
for(i=0;i<m-1;i++)//先按照非闰年计算上个月之前的总天数
{
sum+=a[i];
}
sum+=d;
if(m>2) sum+=isrun(y);//若是瑞年,同时月份在2月份之后,就在总天数上面加1
printf("%d\n",sum);
return 0;
}
六:怪数
寻找怪数:有一种奇怪的自然数,它的比其本身小的所有因子之和等于它本身,例如:6=1+2+3,其中1、2、3都是6的因子,编程找出整数N之内的所有怪数。
输入说明 :
输入一个整数N(10<=N≤10000),在行首和行尾没有多余的空格。
输出说明 :
输出N之内(<=N)的所有怪数,每一行输出一个整数。(注:若N中有3个怪数,你则需要输出三行,每行一个怪数。)所有数据前后没有多余的空格,中间也没有多余的空行。
#include<stdio.h>
#include<math.h>
int main()
{
int n,i,j,sum=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
for(j=1;j<i;j++)//利用for循环从1到数本身判断是否是因子
{
if(i%j==0)
{
sum+=j;//将因子相加
}
}
if(sum==i) printf("%d\n",i);
sum=0;
}
return 0;
}
七:T的倍数n
对于一个个位数为7的自然数N,把它的个位数移到最高位,其余各位均右移一位,要求这样得到的一个新的数是原数的T倍。现给出这个自然数T,求满足这个要求的最小的自然数N。若在[1, 1000000] 的范围内没有找到N,则输出“No”。
输入说明 :
你写的程序要求从标准输入设备(通常,键盘为标准输入设备)中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行仅有一个自然数T(1≤T≤9)。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备(通常,显示屏为标准输出设备)中。每组运算结果输出一个自然数N或“No”,不包括双引号。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。
#include<stdio.h>
#include<math.h>
using namespace std;
int main()
{
int T,n,num;
while(scanf("%d",&T)!=EOF)
{
for(n=1;n<1000001;n++)
{
if(n%10==7)
{
int i=n;
int count=0;
while(i)
{
i/=10;
count++;
}
num=7*pow(10,(double)count-1)+n/10;//移位,把7移到最开端,pow的作用是m的n次方
//printf("num=%d\n",num);
if(num/n==T&&num%n==0)//num是n的T倍
{
printf("%d\n",n);
break;
}
}
}
if(n==1000001) printf("No\n");
}
return 0;
}
八:三角形
“明明,你会用1到9这九个数字组成一个三角形吗?”明明的爸爸问明明。明明被问的很莫名其妙,不明白他爸爸在说什么,于是就问道:“用1到9组成三角形???”“是的,我的要求很简单,给你2个数,一个数作为这个三角形的开始,另一个数决定这个三角形的大小。例如我给你5和6这两个数,你就要组成如下的一个三角形:
5
6 7
8 9 1
2 3 4 5
6 7 8 9 1
2 3 4 5 6 7
明白了吗?”
明明观察了许久,终于看出了门道来,说道:“就是说给我2个数,例如5和6,那我就要从5这个数开始构建一个三角形。第一行为一个数字,第二行为2个数字,以此类推,直到第六行的六个数字,且三角形中的数字都是1到9在循环重复,是这样吗?”“明明真聪明,就是这样。”明明爸爸高兴的说道。于是明明的爸爸给了明明很多组这样的数字,明明也构建出了很多个不同的三角形。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅有一行,每行有两个整数s和n(1≤s≤9,1≤n≤80),其中s表示位于三角形的最顶端的数字,n表示三角形由几行数字组成。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将每组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为构建出来的三角形,三角形中的同一行的数字两两之间用一个空格隔开。每组运算结果与其后一组运算结果之间有一个空行,最后一组运算结果后面没有空行。
注:通常,显示屏为标准输出设备。
#include<stdio.h>
int main()
{
int start,row,i,j,plus=0,tr;
while(scanf("%d%d",&start,&row)!=EOF)
{
plus=0;
for(i=1;i<=row;i++)
{
for(j=1;j<=i;j++)
{
tr=(start+plus)%9==0?9:(start+plus)%9;//从1到9显示
printf("%d",tr);
plus++;
if(j<i)
printf(" ");
}
printf("\n");
}
printf("\n");
}
return 0;
}
九:约瑟夫环2
假设有k个人质和k个绑匪围成一圈。人质的编号从1到k,绑匪的编号从k+1到2k。从编号1开始,每次从其中选出第m个人(隔m-1选出一人)出列。希望求出m的最小值,使得最先出列的k个人都是绑匪,即都是编号从k+1到2k的人。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅一行,每组测试数据有一个整数k(1≤k≤10),表示人质的人数和绑匪的人数。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个整数m,即明明要选定的那个数。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。 注:通常,显示屏为标准输出设备。
#include<stdio.h>
#include<stdlib.h>
typedef struct node{
int data;
struct node *next;
}LinkList,*LinkNode;
LinkList *Init(LinkList *L,int n)
{
LinkNode r,s;
L=(LinkList*)malloc(sizeof(LinkList));
L->next=L;
L->data=1;
r=L;
for(int i=2;i<=n;i++)
{
s=(LinkList*)malloc(sizeof(LinkList));
s->data=i;
r->next=s;
r=s;
}
r->next=L;
return L;
}
int main()
{
LinkList *L;
L=(LinkList*)malloc(sizeof(LinkList));
int k;
while(~scanf("%d",&k))
{
LinkNode u,p;
int count,t;
for(int m=1;;m++)
{
if(k==10) m=93313;//10的情况超时了==分奴做法
if(m<=k) continue;
L=Init(L,2*k);
p=L;
count=0;
while(count<k)
{
for(int i=1;i<m;i++) p=p->next;//找到要删除的节点
if(p->data<=k) break;
//准备交换前后data
u=p->next;
t=p->data;
p->data=u->data;
u->data=t;
//开始删除u
p->next=u->next;
free(u);
count++;
}
if(count==k)
{
printf("%d\n",m);
break;
}
}
}
return 0;
}
十:判断回文质数
因为151既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 号是回文质数。写一个程序来找出范围[a,b](5<= a < b <= 100,000)间的所有回文质数
输入说明 :
仅 1 行: 二个整数 a 和 b(5<= a < b <= 100,000)。
输出说明 :
输出一个回文质数的列表,一行一个。
每行首尾无空格,最后无空行。
#include<stdio.h>
#include<math.h>
using namespace std;
int main()
{
int i,ii,j,a,b;
scanf("%d%d",&a,&b);
for(i=a;i<=b;i++)
{
int d[10];
int p=0,flag=0,flag2=0;
for(j=2;j<=sqrt(i);j++)//判断质数 一定要用sqrt,否则运行超时
{
if(i%j==0) flag2=1;
}
ii=i;
while(ii)//将数字i存入数组
{
d[p]=ii%10;
//printf("%d ",d[p]);
p++;
ii=ii/10;
}
for(int x=0;x<p/2;x++)//判断回文
{
if(d[x]!=d[p-x-1])
flag=1;
}
//printf("%d ",flag);
if(flag2==0&&flag==0)
printf("%d\n",i);
}
return 0;
}
十一:水果价格
一家水果店出售四种水果,每公斤价格的苹果(代码为a)1.5元,橘子(代码为o)1.4元,香蕉(代码为b)1.48元,菠萝(代码为p)1.08元。编一个程序,使售货员只要在键盘上打入货品的代码及重量,计算机将显示货品名、单价、重量及总价。
输入说明 :
你的程序需要从标准输入设备(通常为键盘)中读入多组测试数据。
每组测试数据的第一行为一个整数m,表示有m件货品要被购买。在接下来的m行中,每行输入两个值d,g。d表示货品的代码,g表示重量。两组数据之间没有多余的空行。
输出说明 :
对每组测试数据,你的程序需要向标准输出设备(通常为启动该程序的终端)依次输出一组对应的答案。对应每组输入,输出货品名、单个总价及全部总价。具体格式参照样例输出:第一行apple前为7个空格,之后为2个空格,其他水果名后都是1个空格,sum后没有空格;第二行price后有2个空格,其后关于价格的表示多为占7格2位小数且左对齐,但其中pineapple为占10格2位小数且左对齐,注意sum的价格仍然占7格,如第一组样例中的54.60后还有2个空格;第三行weight后有1个空格,其后的数据与第二行一致。每两组数据之间有一个空行,最后一组测试数据之后没有空行。
#include <stdio.h>
int main()
{
int m;
while(scanf("%d",&m) != EOF)
{
char d;//货物代码,a苹果,o橘子,b香蕉,p菠萝
// 1.5 1.4 1.48 1.08
float g;//新输入重量
float weight[4];//各 水果总重量
double price[4];//各单种水果总金额
double sum_price=0.0;
float sum_weight=0.0;//总重量和总价格
for(int j=0;j<4;j++)
{
weight[j]=price[j]=0.0;//初始化数组
}
for(int i=0;i<m;i++)
{
getchar();
d=getchar();
scanf("%f",&g);
sum_weight+=g;//总重量
switch(d)
{
case 'a':weight[0]+=g; price[0]+=1.5*g;break;
case 'o':weight[1]+=g; price[1]+=1.4*g;break;
case 'b':weight[2]+=g; price[2]+=1.48*g;break;
case 'p':weight[3]+=g; price[3]+=1.08*g;break;
default : break;
}
}
for(int k=0;k<4;k++)
{
sum_price+=price[k];//总金额
}
printf(" apple orange banana pineapple sum\n");
printf("price %-7.2f%-7.2f%-7.2f%-10.2f%-7.2f\n",price[0],price[1],price[2],price[3],sum_price);
printf("weight %-7.2f%-7.2f%-7.2f%-10.2f%-7.2f\n",weight[0],weight[1],weight[2],weight[3],sum_weight);
printf("\n");
}
}
十二:最高频率
明明的爸爸是一位著名的数学家。他在明明很小的时候就发现明明有过人的数学天赋,因此有意培养他对数学的兴趣。一次,明明的爸爸和明明玩起了一个数字游戏,这个游戏的名字叫“最高频率”。在游戏中,明明的爸爸要求明明在一串数字中,找出出现次数最多的那个数字,如果有多个数字出现的次数一样,则取最小的那个数字。明明很快就理解的游戏的规则,开始玩起来。明明的爸爸首先给了明明三个数字: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中的命令行终端)中。每组运算结果为一个整数,即这个数字串中出现次数最多的那个数字;如果有多个数字出现次数一样,则输出其中最小的那个数字。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。
#include<stdio.h>
int main()
{
int n,i,c,high,pos;
while((scanf("%d",&n))!=EOF)
{
int a[200]={0};
for(i=0;i<n;i++)
{
scanf("%d",&c);
a[c]++;
}
high=a[0];
pos=0;
for(i=0;i<200;i++)
{
if(high<a[i])
{
high=a[i];
pos=i;
}
}
printf("%d\n",pos);
}
return 0;
}