PTA上C语言学习,细节方面有收获的地方与PAT乙级刷题心得。
PTA PTA上没有一下子想到方法的题 
下面附上代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include  <stdio.h>  int  main (void )  {	int  m = 0 , n = 0 , hours = 0 , minute = 0 , end_time = 0 ; 	 	scanf ("%d %d" , &m, &n); 	 	hours = m/100 , minute = m%100 ;   	 	hours += n/60 , minute += n-(n/60 )*60 ; 	 	if (minute >= 60 )  		hours += 1 , minute -= 60 ;  	if (minute < 0 ) 		hours -=1 , minute += 60 ;  	 	end_time = hours*100  + minute;  	 	printf ("%d" , end_time); 	 	return  0 ; } 
PTA中做一道题,注意细节心得 
下面附上代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 #include  <stdio.h>  int  gcd (int  a, int  b)  {	int  c = 0 ; 	 	while (b) 	{ 		c = a%b;   		a = b; 		b = c; 	} 	 	return  a; } int  main (void )  {	int  N = 0 , temp = 0 , g = 0 , temp_N = 0 ; 	int  a = 0 , b = 0 , min  = 0 , sum_a = 0 ; 	 	scanf ("%d" , &N); 	temp_N = N;   	 	for (; N; N--)      	{				 		scanf ("%d/%d" , &a, &b); 		 		if (min ) 		{ 			temp = min ;  			min  = (min *b)/gcd(min , b); 			sum_a *= (min /temp), sum_a += (min /b)*a;  		} 		else  			min  = b, sum_a += a; 			 		g = gcd(sum_a, min ); 		sum_a /= g, min  /= g;	 	}  	N = temp_N; 	 	min  *= N; 	g = gcd(sum_a, min ); 	sum_a /= g, min  /= g; 	 	if (min  > 1 ) 	printf ("%d/%d" , sum_a, min ); 	else  	printf ("%d" , sum_a); 	 	return  0 ;  } 
删除子字符串的一道好题 (方法可以掌握) 
下面题解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include  <stdio.h>  #include  <string.h>   int  main (void )  {	char  *p = NULL ; 	char  s[81 ] = {0 }, t[80 ] = {0 }; 	 	gets(s), gets(t); 	 	while (p = strstr (s, t))  	{ 		*p = '\0' ;   		strcat (s, p+strlen (t)); 	} 	 	puts (s); 	 	return  0 ; } 
一道题因为没有注意, 阶乘并不是 a *= a+2, 花了很多时间找错 
下面代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include  <stdio.h>  int  main (void )  {	double  i = 2 ; 	double  sum = 2 , x = 0 , a = 1 , b = 3 ; 	 	scanf ("%lf" , &x); 	 	for ( ; 2 *a/b >= x; a *= i, b *= (2 *(i++) + 1 ))   	sum += 2 *a/b; 	 	sum += 2 *a/b 	 	printf ("%.6lf" , sum); 	 	return  0 ;  } 
平面向量加法 
可以看到题目就是简单的加法, 但是这里考了个知识点, 正是我不知道的. 所以改了好几次才通过.
因为在C语言整数都是不管四舍五入的, 直接舍弃小数部分. 到了浮点数我默认以为保留几位小数时,也是直接舍弃多余小数部分, 但其实是四舍五入.
下面题解.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include  <stdio.h>  int  main (void )  {	double  a = 0 , b = 0 , c = 0 , d = 0 ; 	double  m = 0 , n = 0 ; 	 	scanf ("%lf %lf %lf %lf" , &a, &b, &c, &d); 	m = a+c, n = b+d;  	if (m > -0.05  && m < 0 ) 		m = 0 ; 	if (n > -0.05  && n < 0 ) 		n = 0 ; 	 	printf ("(%.1lf, %.1lf)" , m, n); 	 	return  0 ; } 
查找书籍 gets()后不产生回车。只是把最后输入的回车转化为 ‘\0’ 。
PAT 520 钻石争霸赛 其中2道很简单的题,但做的时候都有一个测试点怎么也过不了。。。当时真想不明白,比赛结束后来看了很久还是没发现错误,很想知道到测试点是什么,但这是不可能的。。。后面一度认为题目对C语言的问题,hh。其实不是,今天找到了问题,2个题还犯了同一种错误,记录一下。
1.首先是简单的求平均成绩,问题就出现在如果成一个人的成绩是0的话,总成绩为0,但人数增加了一个啊。而我们一直使用的分数来确定是否有人存在。。。找这个错误真不容易诶。
代码警示错误。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include  <stdio.h>  int  main (void )  {	int  N = 0 , sum_0 = 0 , sum_1 = 0 ; 	int  n = 0 , score = 0 ; 	int  count_1 = 0 , count_2 = 0 ; 	 	scanf ("%d" , &N); 	while (N--) 	{ 		scanf ("%d %d" , &n, &score); 		if (n) 			sum_1 += score, count_1++; 		else  			sum_0 += score, count_2++;  	}  	 	printf ("%.1lf" , (double )(sum_1+sum_0)/(count_1+count_2)); 	if (count_1) 		printf (" %.1lf" , (double )sum_1/count_1); 	else  		printf (" X" ); 		 	if (count_2)  		printf (" %.1lf" , (double )sum_0/count_2); 	else  		printf (" X" );  	return  0 ; } 
2.下面这个题犯了差不多的错。可以看到,就是倒序输出数字,可以很多方法。我使用的将每位数字先分离出来存入一个数组,在倒序输出。 但这里有一个0的情况,如果数字为0,那分离数字的结果就是什么也没有即什么也不输出。。
这里其实直接转化为字符串输出就好了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include  <stdio.h>  int  main (void )  {	int  a = 0 , b = 0 , i = 0 ; 	char  ch[13 ] = {0 }; 	 	scanf ("%d %d" , &a, &b); 	sprintf (ch, "%d" , a += b); 	 	for (; ch[i]; printf ("%c\n" , ch[i++])); 	 	return  0 ;  } 
总结:2个题遇到同种类型的错误,折磨了我很久,但对自己进行补漏了。注意0的情况很重要。 
3.这个题注意,题目只说了输入的第一个数字没超过1000位,第二个未知的,有点小坑。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include  <stdio.h>  #include  <string.h>  #include  <math.h>  int  main (void )  {	char  a[10001 ] = {0 }, b[2001 ] = {0 };  	int  sum = 0 , lenth1 = 0 , lenth2 = 0 ; 	int  i = 0 ; 	 	gets(a);     lenth1 = strlen (a);      	gets(b);  	while (*b != '-' ) 	{         lenth2 = strlen (b);         if (lenth1 != lenth2)         	printf ("No\n" );         else  		{ 			for (i = 0 ; i < lenth1; i++)         		sum += abs (a[i]-b[i]);                  	if (sum <= 1 )             	printf ("Yes\n" );         	else              	printf ("No\n" ); 		}              		sum = 0 , gets(b);  	}        	return  0 ; } 
4.处理好每次赢输之间的变换。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include  <stdio.h>  #include  <string.h>   int  main (void )  {	char  s[10 ] = {0 }, flag = 0 ; 	int  N = 0 , a[10 ] = {0 }, i = 0 , j = 0 ; 	 	scanf ("%d" , &N); 	for (i = 0 ; i < N; i++) 		scanf ("%d" , &a[i]); 	getchar();  	 	while (1 ) 	{ 		if (!flag) 		{ 			for (i = 0 ; i < a[j%N]; i++) 			{	 				gets(s); 				if (*s == 'E' ) 					return  0 ; 				 				if (*s == 'C' ) 					printf ("Bu\n" ); 				else  if (*s == 'J' ) 					printf ("ChuiZi\n" ); 				else  					printf ("JianDao\n" ); 				flag = 1 ; 			} 		} 		else  		{ 			gets(s); 			if (*s == 'E' ) 				return  0 ; 			if (*s == 'C' ) 				printf ("JianDao\n" ); 			else  if (*s == 'J' ) 				printf ("Bu\n" ); 			else  				printf ("ChuiZi\n" ); 			flag = 0 , j++; 		} 	} 		 	return  0 ; } 
PAT乙级 我要通过 
题目的难点也就是条件三,如果没有理解到位,总是会有条件过不了。。。 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #include  <stdio.h>  int  judge (char  *a)  {	int  flag = 0 , other = 0 ; 	int  p = 0 , t = 0 , i = 0 ; 	int  q = 0 , z = 0 , h = 0 ; 	 	while (a[i]) 	{ 		if (a[i] == 'A' ) 			if (flag == 0 ) 				q++; 			else  if (flag == 1 ) 				z++; 			else  				h++; 		else  if (a[i] == 'P' ) 			p++, flag = 1 ; 		else  if (a[i] == 'T' ) 			t++, flag = 2 ; 		else  			other++; 		if (t == 1  && p == 0 ) 			return  0 ; 		i++;	 	} 	 	if (!other && z && q*z == h && p == 1  && t == 1 ) 		return  1 ; 	return  0 ; 	 } int  main (void )  {	int  n = 0 ; 	char  a[101 ] = {0 }; 	 	scanf ("%d" , &n); 	getchar();  	while (n--) 	{ 		gets(a); 		if (judge(a)) 			printf ("YES\n" ); 		else  			printf ("NO\n" ); 	} 	 	return  0 ; } 
1007 素数对猜想 主要记录一下素数的优化技巧,这个题只是用普通的方法判断会在最后一个测试点超时。
偶数除2之外都不是素数,所以在判断那些是素数时,可以把2单独处理,其他的每次加2,只看奇数。 在素数判断时,先对所要判断的数开平方,时间复杂度大大降低。 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #include  <stdio.h>  #include  <math.h>   int  prime_number (int  a)  {	int  i = 0 , temp = (int )sqrt ((double )a);  	 	for (i = 2 ; i <= temp; i++) 		if (a%i == 0 ) 			return  0 ; 	return  1 ; } int  main (void )  {	int  i = 0 , N = 0 , count = 0 , temp = 0 ; 	 	scanf ("%d" , &N); 	temp = 2 ; 	for (i = 3 ; i <= N; i += 2 )	 		if (prime_number(i)) 			count += i-temp == 2  ? 1 :0 , temp = i; 	printf ("%d" , count); 	 	return  0 ; } 
1008 数组元素循环右移问题 本以为秒答的题,有个测试点,卡半天。我发现写程序什么错误都会犯。。
这里还是先总结一下,关于数组循环移动输出的问题:假设数组:a,长度:len
循环左移n位:a[n+i%len] 循环右移n位:与左移原理一样,只不起始点用总长度减一下:a[(len-(n%len)+i)%n] 题目:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include  <stdio.h>  int  main (void )  {	int  n = 0 , a[200 ] = {0 }, span = 0 , i = 0 ; 	 	scanf ("%d %d" , &n, &span); 	for (i = 0 ; i < n; i++) 		scanf ("%d" , a+i); 	 	printf ("%d" , a[(n-span%n)%n]);   	for (i = 1 ; i < n; i++) 		printf (" %d" , a[(n-span%n+i)%n]); 	 	return  0 ; 	 } 
总结:我都不知道我怎么找这么一个错误的。
1010 一元多项式求导 题目感觉简单,但是好坑。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include  <stdio.h>  int  main (void )  {	int  i = 0 , j = 0 ; 	int  pre = 0 , cur = 0 ; 	 	scanf ("%d %d" , &pre, &cur); 	if (!cur) 		printf ("0 0" ); 	else  	{ 		printf ("%d %d" , pre*cur, cur-1 ); 		while (scanf ("%d %d" , &pre, &cur) != EOF)  			if (cur) 				printf (" %d %d" , pre*cur, cur-1 ); 	 	} 	 	return  0 ;	 } 
总结:对输入的如何限定停止。
1014 福尔摩斯的约会 感觉题目很多都不说明,自己在哪里猜有没有限制条件,结果都有。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include  <stdio.h>  int  main (void )  {	char  s[4 ][61 ] = {0 }, i = 0 , j = 0 , count = 0 ; 	char  *day[8 ] = {" " , "MON" , "TUE" , "WED" , "THU" , "FRI" , "SAT" , "SUN" }; 	 	while (i < 4 ) 		gets(s[i]), i++; 	 	for (i = 0 ; i < 4 ; i += 2 ) 	{ 		for (j = 0 ; s[i][j] && s[i+1 ][j]; j++) 		{ 			if (i == 0  && s[i][j] == s[i+1 ][j]) 			{	 				if (count == 0  && s[i][j] >= 65  && s[i][j] <= 71 ) 				{ 					printf ("%s " , day[s[i][j]-64 ]); 					count++;  				} 				else  if (count == 1  && (s[i][j] >= 'A'  && s[i][j] <= 'N'  || s[i][j] >= 48  && s[i][j] <= 57 ))  				{ 					printf ("%02d:" , s[i][j] >= 48  && s[i][j] <= 57  ? s[i][j]-48  : s[i][j]-55 ); 					break ; 				} 			}  			else  if (i > 1  && s[i][j] == s[i+1 ][j] && (s[i][j] >= 65  && s[i][j] <= 90  || s[i][j] >= 97  && s[i][j] <= 122 )) 			{ 				printf ("%02d\n" , j); 				break ; 			}	 		}	 	} 	 	return  0 ; } 
其中有个平时没注意过的地方,i > 1 && s[i][j] == s[i+1][j] && (s[i][j] >= 65 && s[i][j] <= 90 || s[i][j] >= 97 && s[i][j] <= 122)),对于这判断式,后面有 || 就一定要加上括号,不然它满足了,判断式就直接成立了。。。
总结:注意题目隐含条件。
1015 德才论 这道题自己开始做起来还是挺难的,先分类后冒泡排序,但一般会有测试点超过,果然。后面尝试使用C语言的qsort(),成功了,从这道题,对qsort()使用变得深入很多。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 #include  <stdio.h>  #include  <stdlib.h>   typedef  struct { 	int  id; 	int  d; 	int  c;  }Stu; int  low = 0 , high = 0 ;int  check (const  Stu *a)  {	if (a->d >= high && a->c >= high) 		return  1 ; 	else  if (a->d >= high && a->c >= low) 		return  2 ; 	else  if (a->d >= low && a->c >= low && a->d >= a->c) 		return  3 ; 	else  if (a->d >= low && a->c >= low) 		return  4 ; 	else   		return  5 ; } int  cmp (const  void  *a, const  void  *b)  {	Stu *a1 = (Stu *)a, *b1 = (Stu *)b; 	int  sum = a1->c+a1->d, sum1 = b1->c+b1->d; 	  	if (check(a1) == check(b1)) 	{ 		if (sum == sum1) 		{ 			if (b1->d == a1->d) 				return  a1->id - b1->id; 			else  				return  b1->d - a1->d; 		} 		else  			return  sum1-sum; 	} 	else  		return  check(a1)-check(b1); } int  main (void )  {	int  n = 0 , count = 0 , i = 0 , j = 0 ; 	scanf ("%d %d %d" , &n, &low, &high); 	Stu *stu = (Stu *)malloc (sizeof (Stu)*n); 	 	for (i = 0 ; i < n; i++) 	{ 		scanf ("%d %d %d" , &stu[i].id, &stu[i].d, &stu[i].c); 		count += stu[i].d >= low && stu[i].c >= low ? 1 :0 ; 	} 	 	qsort(stu, n, sizeof (Stu), cmp); 	 	printf ("%d\n" , count); 	for (i = 0 ; i < count; i++) 		printf ("%d %d %d\n" , stu[i].id, stu[i].d, stu[i].c); 	 	return  0 ; } 
总结:这道题主要二点,一:想到先划分类,二:如何使用上qsort()函数。 
1017 A除以B 这个题使用C语言来写就是一个大数除法,使用平常手算除法的思想,从开始除到最后。但是这个题使用python来做的话就只是函数的调用。
C语言: 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include  <stdio.h>  #include  <string.h>   int  main (void )  {	char  s[1001 ] = {0 }; 	int  n = 0 , temp = 0 , ans = 0 , len = 0 , i = 0 ; 	 	scanf ("%s %d" , s, &n); 	len = strlen (s); 	ans = (s[0 ]-48 )/n; 	if (len == 1  || ans)   		printf ("%d" , ans); 		 	temp = (s[0 ]-48 )%n; 	for (i = 1 ; i < len; i++) 	{ 		ans = (temp*10 +s[i]-48 )/n; 		printf ("%d" , ans); 		temp = (temp*10 +s[i]-48 )%n;  	} 	printf (" %d" , temp); 	 	return  0 ; } 
python: 
1 2 3 n = input().split() q, r = divmod(int(n[0 ]), int(n[1 ])) print  (str(q)+' ' +str(r))
总结:对大数除法使用手算除法的第一次简单应用。 
1018 锤子剪刀布 我发现只要题目写起来比自己预想的代码量大,我就会焦躁,感觉题目不会有那么麻烦,想哪里写的罗嗦了 ,怎么这个都不会之类。导致最后就是更不想做题了。这个题就是个例子,开始预想的很简单,代码也少,但这个题确实判断有点繁琐,尽管有简单的写法,也在自己能力之外吧。
麻烦的地方就是图中标注的地方。自己用的好像是一个类似哈希表的东西,因为没学过。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 #include  <stdio.h>  int  main (void )  {	int  n = 0 , i = 0 , max  = 0 , max1 = 0 ; 	char  ch1 = 0 , ch2 = 0 , s[4 ] = {'B' , 'C' , 'J' , 0 }; 	int  a = 0 , b = 0 , c = 0 , map [127 ] = {0 }, map1[127 ] = {0 }; 	 	scanf ("%d" , &n); 	getchar(); 	while (i++ < n) 	{ 		scanf ("%c %c" , &ch1, &ch2); 		getchar(); 		if (ch1 == 'C'  && ch2 == 'J' ) 			a++, map ['C' ]++; 		else  if (ch1 == 'C'  && ch2 == 'B' ) 			c++, map1['B' ]++; 		else  if (ch1 == 'B'  && ch2 == 'J' ) 			c++, map1['J' ]++; 		else  if (ch1 == 'B'  && ch2 == 'C' ) 			a++, map ['B' ]++; 		else  if (ch1 == 'J'  && ch2 == 'B' ) 			a++, map ['J' ]++; 		else  if (ch1 == 'J'  && ch2 == 'C' ) 			c++, map1['C' ]++; 		else  			b++;	 	} 	 	printf ("%d %d %d\n" , a, b, c); 	printf ("%d %d %d\n" , c, b, a); 	 	for (i = 0 ; s[i]; i++) 	{ 		max  = map [s[i]] > max  ? map [s[i]]:max ; 		max1 = map1[s[i]] > max1 ? map1[s[i]]:max1; 	} 	 	for (i = 0 ; s[i]; i++) 		if (map [s[i]] >= max ) 		{ 			printf ("%c " , s[i]); 			break ; 		} 	for (i = 0 ; s[i]; i++) 		if (map1[s[i]] >= max1) 		{ 			printf ("%c" , s[i]); 			break ; 		} 	return  0 ;	 } 
总结:做题就算有简单解法,把当下麻烦的解法写完再说。
1019 数字黑洞 感觉PTA乙级题的坑好多。。不注意的话又是大量时间找错。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #include  <stdio.h>  #include  <string.h>   int  cmp1 (const  void  *a, const  void  *b)  {	char  *p = (char  *)a, *q = (char  *)b; 	return  *q-*p; } int  cmp2 (const  void  *a, const  void  *b)  {	char  *p = (char  *)a, *q = (char  *)b; 	return  *p-*q; } int  re (char  *s, int  (*cmp)(const  void  *, const  void  *))  {	int  n = 0 ; 	qsort(s, strlen (s), sizeof (char ), cmp); 	sscanf (s, "%d" , &n); 	 	return  n; } int  main (void )  {	char  s[5 ] = {0 }; 	int  n = 0 , n_re = 0 ; 	 	scanf ("%d" , &n), sprintf (s, "%04d" , n); 	n = re(s, cmp1), n_re = re(s, cmp2); 	while (n-n_re != 0  && n-n_re != 6174 ) 	{ 		printf ("%04d - %04d = %04d\n" , n, n_re, n-n_re); 		sprintf (s, "%04d" , n-n_re); 		n = re(s, cmp1), n_re = re(s, cmp2); 	} 	printf ("%04d - %04d = %04d\n" , n, n_re, n-n_re); 	 	return  0 ;	 } 
总结:注意逆序一个数字时他前面的0。
1020 月饼 为什么做PTA的题总是很气。。这个题第一个测试点磨了我2个小时???其实也不怪题,只是很多题都考到了我没注意过的小细节。。那也是收获。
我卡了2小时的一个测试点,错误:qsort的比较函数的返回值是int,这次题目的数据是浮点数,所以如果当两个浮点数相差小于1的时候,返回的值为变成int型的0,那就不会发生排序了。即我用的return q->price_single - p->price_single;,当他们2个数相差小于1就返回0,导致结果是不排序。这里正确的写法应该是return q->price_single > p->price_single;,以后都写大于小于了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 #include  <stdio.h>  typedef  struct { 	double  ku, price_all, price_single; }Cake; int  cmp (const  Cake *a, const  Cake *b)  {	return  b->price_single > a->price_single; } int  main (void )  {	Cake cake[1000 ]; 	double  ans = 0 ;  	int  n = 0 , demand = 0 , i = 0 ; 	 	scanf ("%d %d" , &n, &demand); 	for (i = 0 ; i < n; i++) 		scanf ("%lf" , &cake[i].ku); 	for (i = 0 ; i < n; i++) 	{ 		scanf ("%lf" , &cake[i].price_all); 		cake[i].price_single = cake[i].price_all/cake[i].ku; 	} 	qsort(cake, n, sizeof (Cake), cmp); 	 	for (i = 0 ; i < n; i++) 	{ 		if (cake[i].ku <= demand) 		{ 			ans += cake[i].price_all; 			demand -= cake[i].ku; 		} 		else  		{ 			ans += cake[i].price_single*demand; 			break ; 		}  	} 	printf ("%.2lf" , ans); 	 	return  0 ; } 
总结:1.我感觉这个的难点是能不能想到构造结构体。2.对数据不敏感,一直被坑在qsort的比较函数。 
1022 D进制的A+B 就是让写一个10进制数转任意指定的进制数,以前接触过,这里写2种方法。递归与非递归。
注释了的为递归写法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include  <stdio.h>  char  s[] = "0123456789ABCDEF" ;int  main (void )  {	int  a = 0 , b = 0 , d = 0 , c = 0 ; 	char  s1[1000 ] = {0 }, i = 0 ; 	 	scanf ("%d %d %d" , &a, &b, &d);      	for (c = a+b; c; s1[i++] = c%d, c /= d); 	if (!i) 		printf ("0" );  	while (--i >= 0 ) 		printf ("%c" , s[s1[i]]); 	return  0 ; } 
1023 组个最小数 换个算法, 做对了。但一直想不通之前的算法为什么有2个测试点过不了,折磨了我差不多一天。。。找错真的好难,吐槽一下PAT为什么不给出测试点。
错误:我用字符表示整数时是要ASCII-48,但我只考虑到了0-9的情况,当数字大于9后就不能直接减去48了,并且会被当作2个字符处理。 
这里先给出简单的代码:就是先找到第一个非0数先输出,再将其个数减一,最后输出所有。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include  <stdio.h>  int  main (void )  {	int  a[10 ], i = 0 ; 	 	for (i = 0 ; i < 10 ; i++) 		scanf ("%d" , a+i); 	for (i = 1 ; i < 10 ; i++) 		if (a[i]) 		{ 			printf ("%d" , i); 			a[i]--; 			break ; 		} 	for (i = 0 ; i < 10 ; i++) 		while (a[i]) 		{ 			printf ("%d" , i); 			a[i]--; 		} 		 	return  0 ; } 
折磨我的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 #include  <stdio.h>  int  main (void )  {	char  s[150 ] = {0 }, i = 0 , j = 0 , ch = 0 ; 	 	while ((ch = getchar()) != 10 ) 	{ 		if (ch != 32 ) 		{ 			ch -= 48 ;  			while (ch--) 				s[i++] = j+48 ; 			j++; 		} 	} 	 	if (s[0 ] == 48 ) 	{ 		i = 1 ; 		while (s[i++] == 48 ); 		ch = s[i-1 ]; 		s[i-1 ] = s[0 ]; 		s[0 ] = ch; 	}  	 	puts (s); 	return  0 ; }  int  main (void )  {	int  ch = 0 ; 	char  s[150 ] = {0 }, i = 0 , j = 0 ; 	 	while ((scanf ("%d" , &ch))) 	{ 		if (j == 10 ) 			break ;  		while (ch--) 			s[i++] = j+48 ; 		j++; 	} 	 	if (s[0 ] == 48 ) 	{ 		i = 1 ; 		while (s[i++] == 48 ); 		ch = s[i-1 ]; 		s[i-1 ] = s[0 ]; 		s[0 ] = ch; 	}  	 	puts (s); 	return  0 ; } 
总结:找到错后,舒服了。
1024 科学计数法 写起来有点小麻烦,还是思维方法不到位的原因。
在指数为正的时候花了些时间,哪里从小数点后有几位数有效数字分情况的话,条理就会清楚很多。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #include  <stdio.h>  int  main (void )  {	int  n = 0 , i = 1 , flag = 0 ; 	char  s[100000 ] = {0 }, ans[100000 ] = {0 }; 	 	gets(s); 	if (s[0 ] == '-' ) 		flag = 1 ; 		 	while (s[i++] != 'E' ); 	n = atoi(s+i+1 ); 	if (s[i] == '-' ) 	{ 		int  j = 0 , k = 0 ; 		if (n) 		for (j = 0 ; j < n+1 ; j++) 			ans[j] = j == 1  ? '.' :'0' ; 		for (k = 1 ; k < i-1 ; k++) 			if (k != 2 ) 				ans[j++] = s[k]; 	} 	else  	{ 		if  (n < i-4 ) 		{ 			int  j = 0 , k = 1 ; 			for (k = 1 ; j < n+1 ; k++) 				if (k != 2 ) 					ans[j++] = s[k]; 			ans[j++] = '.' ; 			for ( ; k < i-1 ; k++) 				ans[j++] = s[k]; 		} 		else  		{ 			int  j = 0 , k = 0 ; 			for (k = 1 ; k < i-1 ; k++) 				if (k != 2 ) 					ans[j++] = s[k]; 			for (k = 0 ; k < n-(i-4 ); k++) 				ans[j++] = '0' ; 		}	 	} 	 	if (flag) 		putchar ('-' ); 	puts (ans); 	 	return  0 ;		 } 
总结:记住 atoi()函数是字符串转化为整数,与另外一个相对的函数总是记混。 
1025 反转链表 发现对于我现在的水平,做乙级的难题还要磨合磨合。
首先用一个结构体代表每个节点的数据,先储存在一个数组。然后根据的节点next关系使用选择排序对节点进行排序,最后反转。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #include  <stdio.h>  #include  <stdlib.h>  #include  <string.h>   typedef  struct { 	int  addr, data, next; }List; int  main (void )  {	List temp = {0 }; 	int  next = 0 , n = 0 , k = 0 , i = 0 , j = 0 ; 	 	scanf ("%d %d %d" , &next, &n, &k); 	List *list  = (List *)malloc (sizeof (List)*n); 	memset (list , 0 , sizeof (List)*n); 	 	for (i = 0 ; i < n; i++) 		scanf ("%d %d %d" , &list [i].addr, &list [i].data, &list [i].next); 		 	for (i = 0 ; i < n; i++) 	{ 		for (j = i; j < n; j++) 		{ 			if (list [j].addr == next) 			{ 				temp = list [j]; 				list [j] = list [i]; 				list [i] = temp; 				 				next = list [i].next; 				if (next == -1 ) 					n = i+1 ; 				break ; 			} 		} 	} 	 	for (i = 0 ; i < n; i += k) 	{ 		int  l = i, r = i+k-1 ; 		if (r >= n) 			break ; 		while (l < r) 		{ 			temp = list [l]; 			list [l] = list [r]; 			list [r] = temp; 			l++, r--; 		}  	} 	 	for (i = 0 ; i < n; i++) 		if (i == n-1 ) 			printf ("%05d %d -1\n" , list [i].addr, list [i].data); 		else  			printf ("%05d %d %05d\n" , list [i].addr, list [i].data, list [i+1 ].addr); 			 	return  0 ;	 } 
总结:难。 
1026 程序运行时间 这个题的条件:不足 1 秒的时间四舍五入到秒。硬是想了好久。🤣
后面发现,其实影响那个精度的在第一次除以CLK_TCK的时候,一个巧妙的办法就是除完后加0.5。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include  <stdio.h>  int  main (void )  {	int  h = 0 , m = 0 , s = 0 ; 	int  c1 = 0 , c2 = 0 , tck = 100 , ans = 0 ; 	 	scanf ("%d %d" , &c1, &c2); 	ans = (int )((1.0 *(c2-c1)/100 +0.5 ));  	h = ans/3600 ; 	m = ans%3600 /60 ; 	s = ans%3600 %60 ; 	 	printf ("%02d:%02d:%02d" , h, m, s); 	 	return  0 ; } 
1027 打印沙漏 难点:一个高中数学问题,找规律求前等差数列前n项和。打印倒是简单。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include  <stdio.h>  int  main (void )  {	char  ch = 0 ; 	int  n = 0 , i = 0 , row = 0 , j = 0 ; 	 	scanf ("%d %c" , &n, &ch); 	for (i = 0 ; ; i++) 		if (2 *i*(i+2 )+1  > n) 		{ 			row = i-1 ; 			break ; 		} 	 	for (i = 0 ; i < row; i++) 	{ 		for (j = 0 ; j < i; j++) 			putchar (' ' ); 		for (j = 0 ; j < (row*2 +1 )-2 *i; j++) 			putchar (ch); 		putchar (10 ); 	} 	for (i = 0 ; i < row+1 ; i++) 	{ 		for (j = 0 ; j < row-i; j++) 			putchar (' ' ); 		for (j = 0 ; j < 2 *i+1 ; j++) 			putchar (ch); 		putchar (10 ); 	} 	printf ("%d" , n-(2 *row*(row+2 )+1 )); 	 	return  0 ; } 
总结:第一次看到,感觉高中知识都忘完了。真的要好好学习大学高等数学。 
1028 人口普查 这个题用之前上C语言课老师讲的联合位域来存储日期做很简单,但是还是被题目中的0条件卡了很久,这已经是很多次被PAT乙级的0条件卡了,这个条件真不能大意。
1.开始没有注意,在比较的人里开始不能以0为下标,因为0可能是不合法的人。2.当人数为0时,最后只输出一个0。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 #include  <stdio.h>  #include  <stdlib.h>  #include  <string.h>   typedef  union { 	int  data_compare; 	 	struct  	{ 		int  day: 5 ; 		int  month: 4 ; 		int  year: 12 ; 	}; }Date; typedef  struct { 	char  name[10 ]; 	Date date; }People; int  main (void )  {	int  max  = 0 , min  = 0 , i = 0 , flag = 1 ; 	Date date1 = {0 }, date2 = {0 }; 	int  n = 0 , year = 0 , month = 0 , day = 0 , count = 0 ; 	 	scanf ("%d" , &n); 	People *people = (People *)malloc (sizeof (People)*n); 	memset (people, 0 , sizeof (People)*n); 	 	date1.year = 2014 , date1.month = 9 , date1.day = 6 ; 	date2.year = 1814 , date2.month = 9 , date2.day = 6 ; 	while (i < n) 	{ 		scanf ("%s %d/%d/%d" , people[i].name, &year, &month, &day); 		people[i].date.year = year, people[i].date.month = month, people[i].date.day = day; 		 		if (people[i].date.data_compare >= date2.data_compare && people[i].date.data_compare <= date1.data_compare) 		{ 			if (flag) 				max  = i, min  = i, flag = 0 ; 				 			count++; 			if (people[max ].date.data_compare > people[i].date.data_compare) 				max  = i; 			else  if (people[min ].date.data_compare < people[i].date.data_compare) 				min  = i; 		} 		i++; 	} 	 	if (count) 		printf ("%d %s %s" , count, people[max ].name, people[min ].name); 	else  		printf ("0" ); 	return  0 ; } 
总结:这个方法比较日期大小真不错。 
1030 完美数列 
关键在于写循环时注意一个节省时间的技巧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include  <stdio.h>  int  cmp (const  void  *a, const  void  *b)  {	return  *(int  *)a - *(int  *)b; } int  main (void )  {	double  p = 0 ; 	int  n = 0  , a[100000 ], i = 0 , j = 0 , max  = 1 ; 	 	scanf ("%d %lf" , &n, &p); 	for (i = 0 ; i < n; i++) 		scanf ("%d" , a+i); 		 	qsort(a, n, sizeof (int ), cmp); 	for (i = 0 ; i < n; i++) 	{ 		for (j = i+max ; j < n; j++)  		{ 			if (a[j] > a[i]*p) 			{ 				max  = j-i > max  ? j-i : max ; 				break ; 			} 			else  if (j == n-1 ) 			{ 				max  = j-i+1  > max  ? j-i+1  : max ; 				break ; 			} 		} 	} 	printf ("%d" , max ); 	 	return  0 ; 	 } 
总结:遍历时注意能不能节省时间。 
1031 查验身份证 这道题看出,我对权重有误解。。。开始都去乘个0.01。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include  <stdio.h>  int  main (void )  {	int  n = 0 , i = 0 , flag = 0 , sum = 0 ; 	char  a[] = {'1' , '0' , 'X' , '9' , '8' , '7' , '6' , '5' , '4' , '3' , '2' }; 	int  q[17 ] = {7 , 9 , 10 , 5 , 8 , 4 , 2 , 1 , 6 , 3 , 7 , 9 , 10 , 5 , 8 , 4 , 2 }; 	char  s[19 ] = {0 }; 	 	scanf ("%d" , &n); 	getchar(); 	while (n--) 	{ 		gets(s); 		for (i = 0 , sum = 0 ; i < 17 ; i++) 			sum += (s[i]-48 )*q[i]; 		sum = sum%11 ;  		if (a[sum] != s[17 ]) 			printf ("%s\n" , s), flag = 1 ; 	} 	if (!flag) 		printf ("All passed\n" ); 		 	return  0 ; } 
总结:权重。。 
1033 旧键盘打字 关键是统计坏掉的键时注意一个字母坏了,与之对应的大写或小写都要置坏的标志位。这个还要开始就写,不然后面很麻烦。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include  <stdio.h>  int  main (void )  {	int  a[127 ] = {0 }, i = 0 ; 	char  s[100001 ] = {0 }, ch = 0 ; 	 	while ((ch = getchar()) != 10 ) 	{ 		if (ch >= 65  && ch <= 90 ) 			a[ch]++, a[ch+32 ]++; 		else  if (ch >= 97  && ch <= 122 ) 			a[ch]++, a[ch-32 ]++; 		else  			a[ch]++;  	}	 	gets(s); 	 	for (i = 0 ; s[i]; i++) 	{ 		if (a['+' ]) 		{ 				if (a[s[i]] == 0  && (s[i] < 65  || s[i] > 90 )) 					printf ("%c" , s[i]); 		} 		else  		{ 			if (a[s[i]] == 0 ) 				printf ("%c" , s[i]); 		} 	} 	 	return  0 ; } 
总结:无。 
1034 有理数四则运算 我居然一直不知道分数的加减法可以直接写的,还在哪里通分后计算。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 #include  <stdio.h>  void  gcd (long  a, long  b)  {	if (b == 0 ) 	{ 		printf ("Inf" ); 		return ; 	} 	long  a1 = a, b1 = b, c = 0 , flag = 1 ; 	if (a1 < 0 ) 		a1 *= -1 , a *= -1 , flag *= -1 ; 	if (b1 < 0 ) 		b1 *= -1 , b *= -1 , flag *= -1 ; 	if (a) 	{ 		while (b1) 		{ 			c = a1%b1; 			a1 = b1; 			b1 = c; 		} 		a /= a1, b /= a1; 	} 	if (flag < 0 ) 		printf ("(-" ); 	if (a/b && a%b) 		printf ("%ld %ld/%ld" , a/b, a%b, b); 	else  if (a%b) 		printf ("%ld/%ld" , a%b, b); 	else  		printf ("%ld" , a/b); 	if (flag < 0 ) 		printf (")" );  } int  main (void )  {	char  op[5 ] = "+-*/" , i = 0 ;  	long  a1 = 0 , a2 = 0 , b1 = 0 , b2 = 0 ; 	 	scanf ("%ld/%ld %ld/%ld" , &a1, &a2, &b1, &b2); 	for (i = 0 ; i < 4 ; i++) 	{ 		gcd(a1, a2); 		printf (" %c " , op[i]); 		gcd(b1, b2); 		printf (" = " ); 		switch  (op[i]) 		{ 			case  '+' : gcd(a1*b2+a2*b1, a2*b2);break ; 			case  '-' : gcd(a1*b2-a2*b1, a2*b2);break ; 			case  '*' : gcd(a1*b1, a2*b2);break ; 			case  '/' : gcd(a1*b2, a2*b1);break ; 		} 		putchar (10 ); 	} 	 	return  0 ; } 
总结:分数加减法与输出格式的学习。 
1035 插入与归并 关键在于了解插入与归并排序的原理,然后使用qsort来模拟两种排序算法 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include  <stdio.h>  int  cmp (const  void  *a, const  void  *b)  {	return  *(int  *)a - *(int  *)b; } int  main (void )  {	int  i = 0 , j = 0 , flag = 1 , k = 1 ; 	int  n = 0 , a[100 ] = {0 }, b[100 ] = {0 }; 	 	scanf ("%d" , &n); 	for (i = 0 ; i < n; i++) 		scanf ("%d" , a+i); 	for (i = 0 ; i < n; i++) 		scanf ("%d" , b+i); 	 	for (i = 0 ; i < n-1  && b[i] <= b[i+1 ]; i++); 	for (j = i+1 ; a[j] == b[j] && j < n; j++); 	if (j == n) 	{ 		puts ("Insertion Sort" ); 		qsort(a, i+2 , sizeof (int ), cmp); 	} 	else  	{ 		puts ("Merge Sort" ); 		while (flag) 		{ 			k *= 2 ; 			flag = 0 ; 			for (i = 0 ; i < n; i++) 				if (a[i] != b[i]) 					flag = 1 ; 			for (i = 0 ; i < n/k; i++)  				qsort(a+k*i, k, sizeof (int ), cmp); 			qsort(a+n/k*k, n-(n/k*k), sizeof (int ), cmp); 		} 	} 	printf ("%d" , a[0 ]); 	for (i = 1 ; i < n; i++) 		printf (" %d" , a[i]); 		 	return  0 ; } 
总结:排序算法的了解与qsort的运用。 
1040 有几个PAT 做这个的题的思路真是秒啊,果然好想的方法写起来多,不容易想到的方法代码量又少效率又高。
先统计所有’T’的个数,再依次遍历。如果在前面遇到的’P’则P的个数加1,遇到’T’则T的个数减一,遇到’A’则总个数直接加上此时P的个数与T的个数乘积。 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #include  <stdio.h>  int  main (void )  {	char  s[100001 ] = {0 }; 	long  ans = 0 , count_t  = 0 , count_p = 0 , i = 0 ; 	 	gets(s); 	for (i = 0 ; s[i]; i++) 		if (s[i] == 'T' ) 			count_t ++; 			 	for (i = 0 ; s[i]; i++) 	{ 		if (s[i] == 'P' ) 			count_p++; 		else  if (s[i] == 'T' ) 			count_t --; 		else  			ans += count_p*count_t ;  	} 	 	printf ("%d" , ans%1000000007 ); 	 	return  0 ; } 
1041 考试座位号 从这道题找出了以前不清楚的知识点。
scanf();后如果是是用gets()输入字符串,那必须先吃掉回车;如果是用scanf(“%s”, );输入字符串可以不吃掉回车。
成功跳进上图标出的坑。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include  <stdio.h>  #include  <string.h>   typedef  struct { 	char  id[17 ];  	int  z2; }People; int  main (void )  {	char  id_[17 ] = {0 }; 	int  n = 0 , z1_ = 0 , z2_ = 0 , temp = 0 ; 	People people[1001 ] = {0 }; 	 	scanf ("%d" , &n); 	while (n--) 	{ 		scanf ("%s %d %d" , id_, &z1_, &z2_); 		strcpy (people[z1_].id, id_); 		people[z1_].z2 = z2_; 	} 			 	scanf ("%d" , &n); 	while (n--) 	{ 		scanf ("%d" , &temp); 		printf ("%s %d\n" , people[temp].id, people[temp].z2); 	} 	 	return  0 ; } 
1045 快速排序 
这个题关键在于一个点:只要某个元素的位置没有变,我们只要保证左边的元素最大值都比它小,那该元素左边的元素都比它小,右边的元素都比它大。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include  <stdio.h>  int  cmp (const  void  *a, const  void  *b)  {    return  *(int  *)a - *(int  *)b;     } int  main (void )  {	int  N = 0 , i = 0 , count = 0 , max  = 0 ;     int  p[100001 ], p1[100001 ], p2[100001 ]; 	 	scanf ("%d" , &N); 	for (i = 0 ; i < N; i++) 	{ 		scanf ("%d" , &p[i]); 		p1[i] = p[i]; 	} 	qsort(p, N, sizeof (int ), cmp);      	for (i = 0 ; i < N; i++) 	{ 		if (p[i] == p1[i] && p1[i] > max )             p2[count++] = p[i];         if (p1[i] > max )             max  = p1[i]; 	}  	 	printf ("%d\n" , count);     if (count)            printf ("%d" , p2[0 ]); 	for (i = 1 ; i < count; i++)         printf (" %d" , p2[i]);     putchar (10 ); 	 	return  0 ; } 
1048 数字加密 题目不难又是坑人的隐含条件。。
这里说2个整数每一位对应数字进行运算,但有个情况就是B的长度小于A的长度的时候就要在B的前面用’0’补齐与A一样的长度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include  <stdio.h>  #include  <string.h>   int  main (void )  {	int  l_a = 0 , l_b = 0 , i = 0 ;  	char  a[201 ] = {0 }, b[201 ] = {0 }, c[201 ] = {0 }; 	char  s[14 ] = "0123456789JQK" ; 	 	scanf ("%s %s" , a, b); 	l_a = strlen (a), l_b = strlen (b); 	if (l_b < l_a) 	{ 		while (i < l_a-l_b) 			c[i++] = '0' ; 		strcat (c, b); 		strcpy (b, c); 	} 	 	i = 1 , l_b = strlen (b); 	while (i <= l_a) 	{ 		if (i%2 ) 			b[l_b-i] = s[(b[l_b-i]-48 +a[l_a-i]-48 )%13 ]; 		else  		{ 			int  temp = (b[l_b-i]-48 )-(a[l_a-i]-48 ); 			b[l_b-i] = temp < 0  ? temp+10 +48 :temp+48 ; 		} 		i++; 	} 	puts (b); 	  	return  0 ;  } 
1049 数列的片段和 不会动态规划,算法没有学习过,做这个题看了柳神的算法,厉害。。。
算法:算出每个数一共会在片段中出现的次数,然后相乘。最后所有数据相加即可。 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include  <stdio.h>  int  main (void )  {	int  n = 0 , i =1 ; 	double  temp = 0 ; 	long  long  ans = 0 ; 	 	scanf ("%d" , &n); 	for (i = 1 ; i <= n; i++) 	{ 		scanf ("%lf" , &temp); 		ans += (long  long )(temp*1000 )*i*(n-i+1 ); 	} 	printf ("%.2lf" , ans/1000.0 ); 	 	return  0 ; } 
1050 螺旋矩阵 
开始想的是从外层一圈一圈的填充,但是最后也只能填充最外层,内层填充不好插进去。。。 
下面是柳婼 の blog 的填充方法给出的图:真的清晰明了。其实这也是最基本应该想到的常规方法。 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 #include  <stdio.h>  #include  <math.h>   #include  <stdlib.h>  int  a[100000 ] = {0 };int  ans[100000 ] = {0 };int  cmp (const  void  *a, const  void  *b)  {	return  *(int  *)b - *(int  *)a; } void  filling (int  *ans, int  *a, int  m, int  n, int  N)  {	int  i = 0 , j = 0 , level = m/2 +m%2 , t = 0 ; 	 	for (i = 0 ; i < level; i++) 	{ 		for (j = i; j <= n-1 -i && t <= N-1 ; j++) 			ans[i*n+j] = a[t++]; 		for (j = i+1 ; j <= m-2 -i && t <= N-1 ; j++) 			ans[j*n+n-1 -i] = a[t++]; 		for (j = n-1 -i; j >= i && t <= N-1 ; j--) 			ans[(m-1 -i)*n+j] = a[t++]; 		for (j = m-2 -i; j >= i+1  && t <= N-1 ; j--) 			ans[j*n+i] =  a[t++]; 	} } int  main (void )  {	int  i = 0 , j = 0 ; 	int  N = 0 , m = 0 , n = 0 ; 	 	scanf ("%d" , &N); 	n = (int )sqrt (N); 	while (n) 	{ 		if (N%n == 0 ) 		{ 			m = N/n; 			break ; 		} 		n--; 	} 	for (i = 0 ; i < N; i++) 		scanf ("%d" , a+i); 	qsort(a, N, sizeof (int ), cmp); 	 	filling(ans, a, m, n, N); 	for (i = 0 ; i < m; i++) 	{ 		for (j = 0 ; j < n; j++) 		{ 			printf ("%d" , ans[i*n+j]); 			if (j != n-1 ) 				putchar (32 ); 			} 		putchar (10 ); 	} 	 	return  0 ;	 } 
1051 复数乘法 
为什么PAT的题有这么多坑。。首先这里的给的辐角已经是弧度制了,所以不用转换;其次就是结果保留2位小数,那当结果小于0但大于-0.01时,比如-0.001,这时候保留2位小数就只有0,所以最后输出的时候也不应该有负号。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include  <stdio.h>  #include  <math.h>  int  main (void )  {	double  r1 = 0 , p1 = 0 , r2 = 0 , p2 = 0 ; 	double  a1 = 0 , b1 = 0 , a2 = 0 , b2 = 0 ; 	double  ans1 = 0 , ans2 = 0 ; 	 	scanf ("%lf %lf %lf %lf" , &r1, &p1, &r2, &p2); 	a1 = r1*cos (p1); 	b1 = r1*sin (p1); 	a2 = r2*cos (p2); 	b2 = r2*sin (p2); 	ans1 = a1*a2+(-1 )*b1*b2; 	ans2 = a1*b2+a2*b1; 	 	if (ans1 < 0  && ans1 > -0.01 ) 		ans1 = 0 ;	 	if (ans2 < 0  && ans2 > -0.01 ) 		ans2 = 0 ;      	printf ("%.2lf" , ans1); 	if (ans2 >= 0 ) 		putchar ('+' ); 	printf ("%.2lfi" , ans2); 	 	return  0 ; } 
1052 卖个萌 考点:字符串的分割,使用一个指针数组来存储地址。 
写完,在本地C语言环境发现VC与DEVC一得不到正确的结果,调式才发现这2个环境都不能识别输入的表情符号,然后都以0来填充。这也是本题我的难点,找错半天。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #include  <stdio.h>  void  fun (char  *a[], char  *s)  {	int  i = 0 , j = 0 ; 	 	while (s[i]) 	{ 		if (s[i] == '[' ) 			a[j++] = s+i+1 ; 		else  if (s[i] == ']' ) 			s[i] = '\0' ; 		i++; 	} } int  main (void )  {	int  n = 0 , i = 0 ; 	char  *a[3 ][100 ] = {NULL }, s[3 ][100 ] = {0 }; 	int  zs, zy, k, yy, ys; 	 	for (i = 0 ; i < 3 ; i++) 	{ 		gets(s[i]); 		fun(a[i], s[i]); 	} 	scanf ("%d" , &n); 	while (n--) 	{ 		scanf ("%d %d %d %d %d" , &zs, &zy, &k, &yy, &ys); 		if (!a[0 ][zs-1 ] || !a[0 ][ys--] || !a[1 ][zy-1 ] || !a[1 ][yy-1 ] || !a[2 ][k]) 			printf ("Are you kidding me? @\\/@\n" ); 		else  			printf ("%s%s%s%s%s" , a[0 ][zs-1 ], a[1 ][zy-1 ], a[2 ][k], a[1 ][yy-1 ], a[0 ][ys-1 ]); 	} 	 	return  0 ; } 
最后:还有一个注意的地方就是,使用指针数组存放一个数组的指针字符串的地址后,该数组不能改变啊。大意就容易出错。
1054 求平均值 这个题开始自己了判断是否是合法数据的函数,但一只有一个测试点过不了,就开始找判断函数的问题,果然有问题,但修改后仍然有测试点过不了。
原来因为题不中的一句话:如果 K 为 1,则输出 The average of 1 number is Y,这里的number是单数。。。
另外就是这个题,直接用sscanf与sprintf对数据进行相互转换,如果不相等则不合法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include  <stdio.h>  #include  <string.h>  #include  <stdlib.h>  int  main (void )  {	char  s[1000 ] = {0 }, t[1000 ] = {0 }; 	int  n = 0 , count = 0 , i = 0 , flag = 0 ; 	double  sum = 0 , temp = 0 ; 	 	scanf ("%d" , &n); 	while (n--) 	{ 		scanf ("%s" , s); 		sscanf (s, "%lf" , &temp); 		sprintf (t, "%.2lf" , temp); 		 		for (i = 0 ; i < strlen (s); i++) 			if (s[i] != t[i]) 				flag = 1 ; 		if (!flag && temp >= -1000  && temp <= 1000 ) 			sum += temp, count++; 		else  			printf ("ERROR: %s is not a legal number\n" , s); 		strcpy (s, "" ), flag = 0 ; 	} 	if (count == 1 ) 		printf ("The average of 1 number is %.2lf" , sum/count); 	else  if (count) 		printf ("The average of %d numbers is %.2lf" , count, sum/count); 	else  		printf ("The average of 0 numbers is Undefined" ); 		 	return  0 ; } 
1060 爱丁顿数 
难在题目意思开始没有理解。其实就是让我们找到给定骑车天数中,E天骑车超过E英里的最大E。如给定的例子,在给定10天骑车中,有6天骑车都超过6英里。且这个6是能找到最大的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include  <stdio.h>  int  cmp (const  void  *a, const  void  *b)  {	return  *(int  *)a > *(int  *)b ? -1 :1 ; } int  main (void )  {	int  n = 0 , i = 1 , a[100001 ], ans = 0 , p = 1 ; 	 	scanf ("%d" , &n); 	for (i = 1 ; i <= n; i++) 		scanf ("%d" , a+i); 	qsort(a+1 , n, sizeof (int ), cmp); 	 	while (ans <= n && a[p] > p) 		ans++, p++; 	printf ("%d" , ans); 	 	return  0 ; } 
1062 最简分数 
就是上面的一个坑点。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include  <stdio.h>  int  gcd (int  a, int  b)  {	return  b == 0  ? a : gcd(b, a%b); } void  swap (double  *a, double  *b)  {	double  temp = *a; 	*a = *b; 	*b = temp; } int  main (void )  {	int  i = 0 , count = 0 , k = 0 ; 	double  a, a1, b, b1; 	 	scanf ("%lf/%lf %lf/%lf %d" , &a, &a1, &b, &b1, &k); 	a *= k/a1, b *= k/b1; 	if (a > b) 		swap(&a, &b); 	b = b>(int )b ? b+1 :b; 	 	for (i = (int )a+1 ; i < (int )b; i++) 		if (gcd(i, k) == 1 ) 			if (count == 0 ) 				printf ("%d/%d" , i, k), count = 1 ; 			else  				printf (" %d/%d" , i, k); 					 	return  0 ; } 
1065 单身狗 真的吐了,又是被PAT乙级输出格式找了半天错。
另外就是,还是0作怪。。我用0做存放夫妻数组的初始化,让夫妻达到相互映射关系,但是忘了有夫妻的id是0啊。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include  <stdio.h>  int  main (void )  {	int  n = 0 , count = 0 , i = 0 ; 	int  a[100000 ], b[100000 ] = {0 }; 	 	scanf ("%d" , &n); 	for (i = 0 ; i < 100000 ; i++) 		a[i] = -1 ; 	while (n--) 	{ 		int  id1, id2; 		scanf ("%d %d" , &id1, &id2); 		a[id1] = id2, a[id2] = id1; 	} 	scanf ("%d" , &n); 	while (n--) 	{ 		int  id; 		scanf ("%d" , &id); 		b[id]++; 	} 	for (i = 0 ; i < 100000 ; i++) 		if (b[i] && (a[i] < 0  || !b[a[i]])) 			count++, b[i] = -1 ; 			 	printf ("%d\n" , count); 	for (i = 0 ; i < 100000 ; i++) 		if (b[i] == -1  && count > 1 ) 			printf ("%05d " , i), count--; 		else  if (b[i] == -1 ) 			printf ("%05d" , i); 			 	return  0 ; }