3.1 简单模拟
(1)B1032
为了用事实说明挖掘机技术到底哪家强,PAT 组织了一场挖掘机技能大赛。现请你根据比赛结果统计出技术最强的那个学校。
输入格式:
输入在第 1 行给出不超过 105 的正整数 N,即参赛人数。随后 N 行,每行给出一位参赛者的信息和成绩,包括其所代表的学校的编号(从 1 开始连续编号)、及其比赛成绩(百分制),中间以空格分隔。
输出格式:
在一行中给出总得分最高的学校的编号、及其总分,中间以空格分隔。题目保证答案唯一,没有并列。
输入样例:
6
3 65
2 80
1 100
2 70
3 40
3 0
输出样例:
2 150
题解:
难度很低的题往往笑里藏刀~
(1)WA:下面代码的pos初值不能设为0,根据题意肯定是个正整数,万一数据只有一行,且分数为0呢,此时应该输出1,而你输出pos原始值0,嗐,WA了
(2)超时:不要傻傻地用二重循环,你肯定能发现其实total数组的下标就是学校的标号,因此一次循环就OK。
#include <iostream>using namespace std;struct comp{int num;int grade;}cmp[100001];int total[100001]={0};int main(){int n;cin>>n;for(int i=1;i<=n;++i){scanf("%d",&cmp[i].num);scanf("%d",&cmp[i].grade);total[cmp[i].num]+=cmp[i].grade;}int pos=1;for(int i=1;i<=n;++i){if(total[pos]<total[i]){pos = i;}}printf("%d %d",pos,total[pos]);return 0;}
(2)3-1-A
题目描述
有一个长度为整数L(1<=L<=10000)的马路,可以想象成数轴上长度为L的一个线段,起点是坐标原点,在每个整数坐标点有一棵树,即在0,1,2,…,L共L+1个位置上有L+1棵树。
现在要移走一些树,移走的树的区间用一对数字表示,如 100 200表示移走从100到200之间(包括端点)所有的树。
可能有M(1<=M<=100)个区间,区间之间可能有重叠。现在要求移走所有区间的树之后剩下的树的个数。
输入
两个整数L(1<=L<=10000)和M(1<=M<=100)。
接下来有M组整数,每组有一对数字。
输出
可能有多组输入数据,对于每组输入数据,输出一个数,表示移走所有区间的树之后剩下的树的个数。
样例输入
样例输出
2 5
题解:
这道题如果读者的思路是,每次输入判断是不是和之前有重叠,如果这样重叠该怎么办,那样重叠该怎么办······ 那估计是gg了。
笔者认为比较合理的做法是:设一个数组,把a[0]~a[L]都设成1,每组输入就把区间内的元素改为0.不管重不重叠,这样,最后只需求数组的sum即为最后的AC代码~
#include <cstdio>int main(){int L;int m;while (scanf("%d %d",&L,&m)!=EOF){if(L==0&&m==0) break;int i,sum=0;int a[L+1];for(i=0;i<L+1;++i){a[i]=1;}for(int k=0;k<m;++k){int s,t;scanf("%d %d",&s,&t);for(int j=s;j<=t;++j){a[j]=0;}}for(int k=0;k<L+1;++k){sum+=a[k];}printf("%d\n",sum);}return 0;}
(3)3-2-B
题目描述
给定两个整数A和B,其表示形式是:从个位开始,每三位数用逗号”,”隔开。
现在请计算A+B的结果,并以正常形式输出。
输入
输入包含多组数据数据,每组数据占一行,由两个整数A和B组成(-10^9 < A,B < 10^9)。
输出
样例输入
-234,567,890 123,456,789
1,234 2,345,678
样例输出
-111111101
2346912
题解:
(1)记住字符转数字函数
(2)字符1和数字1 ASC相差48
(3)char数组最后会有\0结尾,因此要多给一个空间,至少开辟13个长度
#include <stdio.h>#include <stdlib.h>#include <string.h>long transform(char *a,int len);//将数组转化为整型int main(){char a[13],b[13];int len1,len2;long A,B;while(scanf("%s%s",a,b)!=EOF){len1=strlen(a);len2=strlen(b);A=transform(a,len1);B=transform(b,len2);printf("%ld\n",A+B);}return 0;}long transform(char *a,int len){int sum=0,j=1,i;for(i=len-1; i>=0; i--){if(a[i]>='0'&&a[i]<='9'){sum+=(a[i]-48)*j;j*=10;}}if(a[0]=='-')sum=-sum;return sum;}
3.2 查找元素
(1)3-2-B
题目描述
输入一个数n,然后输入n个数值各不相同,再输入一个值x,输出这个值在这个数组中的下标(从0开始,若不在数组中则输出-1)。
输入
测试数据有多组,输入n(1<=n<=200),接着输入n个数,然后输入x。
输出
样例输入
样例输出
2
题解:
题不难,陷阱不少,需要注意的地方很多,这道题codeup网站上AC率只有20%多一点,其他题多数是65%以上,一般错我都是因为考虑不全导致WA。
(1)忽略-1导致WA:题里说啦,不在数组中输出-1,别不做处理!!!!
(2)忽略多组输入:不知道黑盒数据有多少,要用EOF,不是只有一组输入 !!
(3)忽略换行\n : 多数题目只有1个输出就结束程序,即使不加\n也一样AC,导致学生习惯不加最后的\n, 这道题就不一样,多组输入,不加\n,会出问题。
#include <cstdio>int a[202];int main(){int n;while (scanf("%d",&n)!=EOF){for(int i=0;i<n;++i){scanf("%d",&a[i]);}int key;scanf("%d",&key);for(int i=0;i<n;++i){if (key == a[i]){printf("%d\n", i);break;}if (i == n - 1 && key != a[i]){printf("-1\n");}}}return 0;}
3.4 日期处理
(1) 3-4-A
题目描述
有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天。
输入
有多组数据,每组数据有两行,分别表示两个日期,形式为YYYYMMDD
输出
样例输入
样例输出
题解:
(1)日期的输入只有8位,当作int处理更方便(字符串很麻烦),然后通过%和/ 分离出年月日,再进一步处理
(2)总思路:把date1不断的++(只要date1<date2),d1达到当月天数上限,就置1,m1++,当m1达到13时,m1之1,y1++
(3)为了更加方便地取出当月的天数,我们设计isLeap函数判断平年闰年,并用二维数组a[13][2]存储天数,a[][0]表示平年,a[][1]表示闰年
//3-4-A (日期差值)#include <cstdio>bool isLeap (int y){return ((y%4==0&&y%100!=0)||(y%400==0));}int main(){//a[][0]是平年 a[][1]是闰年int month[13][2]={{0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},{31,31},{30,30},{31,31},{30,30},{31,31}};int date1,date2;while (scanf("%d%d",&date1,&date2)!=EOF){if (date1 > date2){int temp = date2;date2 = date1;date1 = temp;}if (date1 == date2){printf("1\n");}if (date1 < date2){int sum = 1;int y1, m1, d1;int y2, m2, d2;y1 = date1 / 10000;m1 = (date1 % 10000) / 100;d1 = date1 % 100;y2 = date2 / 10000;m2 = (date2 % 10000) / 100;d2 = date2 % 100;while (y1 < y2 || m1 < m2 || d1 < d2){d1++;if (d1 == (month[m1][isLeap(y1)]) + 1){m1++;d1 = 1;}if (m1 == 13){y1++;m1 = 1;}sum++;}printf("%d\n", sum);}}return 0;}
3.5 进制转换
综述:进制转换主要分为(P进制转十进制&十进制转P进制)

// 将P进制数x转换为十进制数yint y = 0, product = 1; //product在循环中不断乘P,得到1、P、P^2、P^3 ···while(x!=0){y = y + (x%10)*product; // 每次把x的最后一位乘productx = x/10; // 把x去掉个位product = product*P;}

// 将十进制数y转换为Q进制,结果存放于数组zint z[40], num = 0;do{z[num] = y%Q; //除基取余++num;y = y/Q;}while(y!=0); //当商不为0时进行循环
这样操作后,结果就倒序存在数组中,即z数组从高位z[num-1]到低位z[0]即为Q进制z,进制转换完成。
(1)3-5-A
题目描述
输入两个不超过整型定义的非负10进制整数A和B(<=231-1),输出A+B的m (1 < m <10)进制数。
输入
输入格式:测试输入包含若干测试用例。每个测试用例占一行,给出m和A,B的值。
当m为0时输入结束。
输出
样例输入
样例输出
提示
注意输入的两个数相加后的结果可能会超过int和long的范围。
题解:
Nothing to say. Just notice the notice and design the type of (a+b) as “unsigned int”.
#include <cstdio>int main(){int a,b,d;unsigned int c;while (true){int r[50]={0},num=0;scanf("%d",&d);if(d==0){break;}scanf("%d%d",&a,&b);c = a+b;do{r[num] = c%d;++num;c = c/d;}while (c!=0);for(int i=num-1;i>=0;--i){printf("%d",r[i]);}printf("\n");}return 0;}
3.6 字符串处理
给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。
输入格式:
测试输入包含一个测试用例,在一行内给出总长度不超过 80 的字符串。字符串由若干单词和若干空格组成,其中单词是由英文字母(大小写有区分)组成的字符串,单词之间用 1 个空格分开,输入保证句子末尾没有多余的空格。
输出格式:
输入样例:
输出样例:
Come I Here World Hello
#include <cstdio>#include <cstring>int main(){char ans[1000][1000];int num = 0;while (scanf("%s",ans[num])!=EOF){++num;}for(int i=num-1;i>=0;--i){printf("%s",ans[i]);if(i>0) printf(" ");}return 0;}
