仅以此Blog记录PAT甲级习题训练过程
1001. A+B Format ★
Tips:
-
首先判断和的正负,这个比较容易考虑到.
- 从高位开始输出,每三位一个分隔,要注意若更高位有过输出,则次位输出的时候不够三位记得补0.
#includeint main() { int a,b,c,temp; int flag1,flag2; while(scanf("%d %d",&a,&b) != EOF){ c = a + b; flag1 = flag2 = 0; if(c < 0){ printf("-"); c = -c; } if(c / 1000000 > 0){ printf("%d,",c / 1000000); c = c % 1000000; flag1 = 1; } if(c / 1000 > 0 || flag1 == 1){ temp = c / 1000; if(flag1 == 1){ if(temp > 9 && temp < 100) printf("0"); else if(temp < 10) printf("00"); } printf("%d,",temp); c = c % 1000; flag2 = 1; } if(flag2 == 1){ if(c > 9 && c < 100) printf("0"); else if(c < 10) printf("00"); } printf("%d\n",c); } return 0; }
1002. A+B for Polynomials ★
Tips:
-
double数组必须初始化为0.默认虽为0,但是是不准确的0.
-
第2行输入的数据在加之前要判断num[i]是不是0,加之后也要判断下是否为0,再对count进行响应操作.
-
最后打印数据的时候空格放在数据前打印,若放在后面会造成最后一个数据也打印一个空格,从而格式错误.
#include#define LEN 1001 int main() { double num[LEN]; int k,a,count,i; double b; while(scanf("%d",&k) != EOF){ count = 0; for(i = 0;i < LEN;i++) num[i] = 0; for(i = 0;i < k;i++){ scanf("%d",&a); scanf("%lf",&b); num[a] += b; count ++; } scanf("%d",&k); for(i = 0;i < k;i++){ scanf("%d",&a); scanf("%lf",&b); if(num[a] == 0) count ++; num[a] += b; if(num[a] == 0) count --; } printf("%d",count); if(count != 0){ for(i = LEN - 1;i >= 0;i--){ if(num[i] != 0){ printf(" %d %.1lf",i,num[i]); num[i] = 0; } } } printf("\n"); } }
1005. Spell It Right ★
Tips:
- 这题算是很简单的一道题了,注意单词不要拼写错误就行.
#includechar* converse(int n){ switch(n){ case 0: return "zero"; case 1: return "one"; case 2: return "two"; case 3: return "three"; case 4: return "four"; case 5: return "five"; case 6: return "six"; case 7: return "seven"; case 8: return "eight"; case 9: return "nine"; default: return ""; } } int main(){ char c ; int sum = 0; while((scanf("%c",&c) != EOF)){ if(c != 10){ sum += c - 48; }else{ if(sum > 99) printf("%s %s %s\n",converse(sum / 100),converse(sum % 100 / 10),converse(sum % 10)); else if(sum > 9) printf("%s %s\n",converse(sum / 10),converse(sum % 10)); else printf("%s\n",converse(sum)); sum = 0; } } return 0; }
1006. Sign In and Sign Out ★
Tips:
- 这题没什么陷阱,基本上例子能通过也就能AC,所以通过率也蛮高的.
- 本题看似有些复杂,需要把字符串时间转换成我们熟悉的int类型来判断时间的早晚.其实这里有个更方便的方法,就是直接利用strcmp(str1,str2)来比较时间.
- 注意输完M后getchar()掉回车.
#include#include <string.h> int main(){ int n,i; char openPer[16],lockPer[16]; char openTime[9],lockTime[9]; char person[16],inTime[9],outTime[9]; while((scanf("%d",&n) != EOF)){ if(n == 0) continue; getchar(); for(i = 0;i < n;i++){ scanf("%s %s %s",person,inTime,outTime); if(i == 0){ strcpy(openPer,person); strcpy(lockPer,person); strcpy(openTime,inTime); strcpy(lockTime,outTime); continue; } if(strcmp(openTime,inTime) > 0){ strcpy(openPer,person); strcpy(openTime,inTime); } if(strcmp(lockTime,outTime) < 0){ strcpy(lockPer,person); strcpy(lockTime,outTime); } } printf("%s %s\n",openPer,lockPer); } return 0; }
1007. Maximum Subsequence Sum ★★
Tips:
- 这题真心是郁闷要死了.自己没有看太清题目,加上题目给的实例又比较特殊,我一直以为后面是输出最大序列的左右两个下标,结果一直只对两个点.后来网上查了下别人的blog再仔细对了下题目,才发现自己理解错误.
- 本题注意的点:(1)数列全为负数输出第一位和最后一位.(2)如果数列最大为0,则输出0 0 0即可.(3)如果数列最大子数列最左项和最右项不能为0.
- 本题一次循环即可得出结果.边输入边用max2加上刚输入的数,并用max1保存最大的max1,并记录下最左和最右的数.
#includeint main(){ int k,i,j,max1,max2,index,num,left1,right1,left2,right2,first,flag; while((scanf("%d",&k) != EOF)){ max1 = 0; max2 = 0; flag = 0; left1 = -1; i = j = -1; for(index = 0;index < k;index++){ scanf("%d",&num); if(index == 0) first = num; if(num >= 0) flag = 1; max2 += num; if(max2 <= 0){ max2 = 0; i = j = -1; }else{ if(i == -1){ i = j = 1; left2 = right2 = num; } else{ j = 1; right2 = num; } if(max2 > max1){ max1 = max2; left1 = left2; right1 = right2; } } } if(flag == 0){ left1 = first; right1 = num; }else{ if(left1 == -1) left1 = right1 = 0; } printf("%d %d %d\n",max1,left1,right1); } return 0; }
1008. Elevator ★
Tips:
- 这题实在没什么难度,也就不说什么了.
#includeint main(){ int n,floor,time,last,gap,i; while((scanf("%d",&n) != EOF)){ time = 0; last = 0; for(i = 0;i < n;i++){ scanf("%d",&floor); gap = floor - last; if(gap > 0) time += 6 * gap; else time -= 4 * gap; last = floor; } time += 5 * n; printf("%d\n",time); } return 0; }
1009. Product of Polynomials ★
Tips:
- 本题与1002类似,只不过此题是求乘积,但和1002注意的地方一样.
- 还需注意的是,本题开辟的数组空间大小应为2001.
#includeusing namespace std; #define LEN 2001 int main() { int k1,k2,i,j,count; int *pCoe; double *pIndex; int coe; double index; double *result = new double[LEN]; for(i = 0;i ) result[i] = 0; while(scanf("%d",&k1) != EOF) { count = 0; pCoe = new int[k1]; pIndex = new double[k1]; for(i = 0;i < k1;i ++) scanf("%d %lf",&pCoe[i],&pIndex[i]); scanf("%d",&k2); for(i = 0;i < k2;i ++){ scanf("%d %lf",&coe,&index); for(j = 0;j < k1;j ++){ if(result[coe + pCoe[j]] == 0) count ++; result[coe + pCoe[j]] += index * pIndex[j]; if(result[coe + pCoe[j]] == 0) count --; } } printf("%d",count); for(i = LEN - 1;i >= 0;i --){ if(result[i] != 0){ printf(" %d %.1lf",i,result[i]); result[i] = 0; } } printf("\n"); } return 0; }
1011. World Cup Betting ★
Tips:
- 太简单了,没啥好说的.
#includeint main(){ int i; float d[3][3]; float dMax[3]; char t[3] = {'W','T','L'}; char c[3]; float money; while(scanf("%f %f %f",&d[0][0],&d[0][1],&d[0][2]) != EOF){ scanf("%f %f %f",&d[1][0],&d[1][1],&d[1][2]); scanf("%f %f %f",&d[2][0],&d[2][1],&d[2][2]); for(i = 0;i < 3;i ++){ dMax[i] = d[i][0]; c[i] = t[0]; if(dMax[i] < d[i][1]){ dMax[i] = d[i][1]; c[i] = t[1]; } if(dMax[i] < d[i][2]){ dMax[i] = d[i][2]; c[i] = t[2]; } } printf("%c %c %c %.2lf\n",c[0],c[1],c[2],(dMax[0] * dMax[1] * dMax[2] * 0.65 - 1) * 2); } return 0; }
1015. Reversible Primes ★
Tips:
- 这题开始一直没太弄懂题目,以为给出的数是以d为底,相当于d进制(但各位可能比d大),然后转换成10进制,再倒置.结果只能过一个点.而且如果按照我的思路,第二个case应该是No才对.
- 最后只能搜搜其它人的答案了.原来是这样做的:先把给出的十进制数转换成d进制,然后这个d进制再逆置,再转换成十进制,再判断.
- 最后借鉴了某位浙大大神的代码,其中的转置处理的很nice.原blog地址http://blog.csdn.net/sunbaigui/article/details/8657051.
#includeint isPrime(int n){ int i; if(n < 2) return 0; for(i = 2;i * i <= n;i ++){ if(n % i == 0) return 0; } return 1; } int numReserve(int n,int d){ int sum = 0; while(n > 0){ sum = sum * d + n % d; n /= d; } return sum; } int main(){ int n,d; while(scanf("%d",&n)){ if(n < 0) break; scanf("%d",&d); if(isPrime(n) && isPrime(numReserve(n,d))) printf("Yes\n"); else printf("No\n"); } return 0; }
1027. Colors in Mars ★
Tips:
- 注意大小写.
#includevoid p(int a){ char c; if(a < 10) c = a + '0'; else{ switch(a){ case 10: c = 'A'; break; case 11: c = 'B'; break; case 12: c = 'C'; break; } } printf("%c",c); } int main(){ int color[3]; int i,a,b; while(scanf("%d %d %d",&color[0],&color[1],&color[2]) != EOF){ printf("#"); for(i = 0;i < 3;i++){ p(color[i]/13); p(color[i]%13); } printf("\n"); } return 0; }
1077. Kuchiguse ★
Tips:
- 此题采用的是边输入边比较的方法,拿第一次输入的字符串依次和后面输入的字符串进行比较,left下标非递减.
- 因为读入的字符串可能带有空格,于是乎gets(common)连续执行了两次才去除了回车的麻烦.具体原因还没深究,标记下以后再来更新.
- 中间循环体加入了left<=rigth,这样如果前面有完全不匹配的字符串时,left就会赋值大于right,从而不再执行循环的内容.
- 相同代码用Java实现过,有一个点超时.所以在写题的时候,尽量用C/C++吧.
#include#include <string.h> int main(int argc, const char * argv[]) { int n,i,j,k,left,right; char common[256],c[256]; while(scanf("%d",&n) != EOF) { gets(common); gets(common); left = 0; right = strlen(common) - 1; for(i = 1;i < n;i++){ gets(c); for(j = right,k = strlen(c) - 1;j >= left && k >= 0 && left <= right;j--,k--){ if(common[j] != c[k]){ break; } } left = ++j; } if(left > right) printf("nai\n"); else{ for(i = left;i <= right;i++) printf("%c",common[i]); printf("\n"); } } return 0; }
1078. Hashing ★★
Tips:
- 说到此题真是略显辛酸.3月份做这题的时候犯过错,现在又犯了同样的错.务必看清题目啊,题目说的很清楚,用平方探测法处理冲突,怎么就是不长眼呢?
- 素数的计算.也挺久没遇到素数了,突然一下子忘了2是不是素数,然后想当然的认为它不是.以后碰到这种问题得好好思考思考,网上查查,确认之后再写.不然写到后面把前面的问题给忽略了,就会一直找不到错误在哪.
- C/C++的一些基本的原理还是没高清.给数组开辟新空间后如果没释放掉,后面再给它开辟新空间的话,可能会引用旧的地址空间,而且旧的数据也还在.而我继续想当然地认为new之后数组各位都为0.后来尝试过delete[],发现不起作用,于是用笨方法,每位设为0.
- 最后就是注意最后一个输出不要有空格.
- 心好累,慢慢捡起来吧.
#includeint getPrime(int size){ int i,k; if(size < 3) return 2; if(size == 3) return 3; while(true){ k = size / 2; for(i = 2;i <= k;i ++){ if(size % i == 0) break; } if(i > k) return size; ++size; } } int main() { int size,n,num,extra,i,j,k; int *hash,*loc; while(scanf("%d %d",&size,&n) != EOF) { if(n == 0) continue; size = getPrime(size); hash = new int[size]; loc = new int[n]; for(i = 0;i < size;i++) hash[i] = 0; for(i = 0;i < n;i++) loc[i] = 0; for(i = 0;i < n;i++){ scanf("%d",&num); extra = num % size; for(j = extra,k = 0;k < size ;j = (extra + k * k) % size){ if(hash[j] == 0) { loc[i] = j; hash[j] = 1; break; } k++; } if(k >= size ) loc[i] = -1; } printf("%d",loc[0]); for(i = 1;i < n;i++){ if(loc[i] == -1) printf(" -"); else printf(" %d",loc[i]); } printf("\n"); } return 0; }
1079. Total Sales of Supply Chain ★
Tips:
- 真是no zuo no die.说好的尽量用C来写,脑子一抽,又用Java来写了,最直接的方法,结果来了个超时.好吧,以为是算法问题,继续改,各种思路,仍得不到解决.换C++吧,还是各种思路,没能AC.最后想试试看用C++来写最开始的最直接的方法,呵呵,AC了...再说一遍,没什么事别用Java!!!
- 这题没什么技巧,也没什么陷阱,无非就先把输入的数据用二维数组保存起来,然后用到了队列.其它没什么好说的了.虽然是个25分的题,但我认为难度不大,只能给一星.
#include "iostream" using namespace std; int main(int argc, const char * argv[]) { int n,i,j,m,len,index; double p,r,amount; int **chain,*tree; double *price; while (scanf("%d %lf %lf",&n,&p,&r) != EOF) { chain = new int*[n]; tree = new int[n]; price = new double[n]; price[0] = p; amount = 0.0; for(i = 0;i < n;i++){ scanf("%d",&m); if(m == 0) len = 2; else len = m + 1; chain[i] = new int[len]; chain[i][0] = m; for(j = 1;j < len;j++) scanf("%d",&chain[i][j]); } tree[0] = 0; for(i = 0,index = 1;i < n;i++){ if(chain[tree[i]][0] == 0) amount += price[tree[i]] * chain[tree[i]][1]; else{ for(j = 1;j <= chain[tree[i]][0];j++){ tree[index++] = chain[tree[i]][j]; price[chain[tree[i]][j]] = price[tree[i]] * (1 + r / 100); } } } printf("%.1lf\n",amount); } return 0; }