第一次练习总结

第一次练习总结

问题:

  • 做的人有些少,做够3个题AC可以得到平时成绩
  • 有助教反映存在抄代码的问题.注意只抄代码不能提高编程水平
  • 而且考试的时候没的抄 平时练习的时候一定打好基础:)

AC代码(仅供参考 别照抄)

A 一道水题

  • 注意格式控制字符%printfformat字符串中要写成%%
  • 这是个送分题:)
#include <stdio.h>
int main(){
	int a,b;
	scanf("%d%d",&a,&b);
	printf("%d %% %d = %d",a,b,a % b);
	return 0;
}

B 分数约分

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <time.h>
#pragma warning(disable:4996)

int gcd(int m,int n){
	return m % n == 0?n:gcd(n,m % n);
}
int main(){
	int m,n,sign;
	while(~scanf("%d%d",&m,&n)){
		sign = 0;
		//preprocess
		if(n < 0){
			n = -n;
			sign = 1;
			if(m < 0){
				m = -m;
				sign = 0;
			}
			else if(m == 0){
				puts("0");
				continue;
			}

		}
		else if(n > 0){
			if(m < 0){
				m = -m;
				sign = 1;
			}
			else if(m == 0){
				puts("0");
				continue;
			}
		}
		else{//n==0
			continue;
		}
		//end preprocess m>0 n>0
		int g = gcd(m,n);
		int a = m / g;
		int b = n / g;
		int res = a / b,mod = a % b;
		if(res){
			if(mod){
				if(sign){
					printf("-%d-%d/%d\n",res,mod,b);
				}
				else{
					printf("%d+%d/%d\n",res,mod,b);
				}
			}
			else{
				if(sign){
					putchar('-');
				}
				printf("%d\n",res);
			}
		}
		else{
			if(mod){
				if(sign){
					printf("-%d/%d\n",mod,b);
				}
				else{
					printf("%d/%d\n",mod,b);
				}
			}
		}
	}
	return 0;
}

C 字母频率统计

  • 如需使用islower,isupper,tolower,toupper记得#include <ctype.h>
  • 思路:不停的读字符,如果读到是大写字母直接计数,如果是小写字母转换成大写字母再计数.
  • 浮点数除法 关注输出要求.
#include <stdio.h>
#include <ctype.h>
int main(){
int c,i;
	double rate;
	int total = 0;
	int a[26] = {0};
	while((c = getchar()) != EOF){
		if(islower(c))c = toupper(c);
		if(c >= 'A' && c <= 'Z'){
			a[c - 'A']++;
			total++;
		}
	}
	for(i = 0;i < 26;i++){
		if(a[i] > 0){
			rate = (double)a[i] / total;
			printf("%c %.2lf%%\n",i + 'A',rate*100);
		}
	}
return 0;
}

D 水君的价格

  • 热身赛好像有个类似的题目 注意数据范围和格式化输出的写法
  • 只用算*2就好了 最后补0
#include <stdio.h>

int main(int argc, const char * argv[]) {
    long long n;
    long long unsigned x;
    while (scanf("%lld",&n)!=EOF) {
        if (n>0) {
            x=2*n;
            printf("%llu00\n",x);
        } else if(n<0){
            x=-n;
            x=2*x;
            if (x==0) {
                puts("-1844674407370955161600");
            }else{
                printf("-%llu00\n",x);
            }
        }else if (n==0){
            printf("0\n");
        }
    }
    return 0;
}

E 漏沙漏

  • 逻辑有些恶心.核心是找规律确定字符的出现位置.(规律找到就舒服些)
  • 奇数和偶数分别处理
#include <stdio.h>
int main(){
	int n,m,i,j,h;
	scanf("%d%d",&n,&m);
	h = n % 2 == 0?n / 2:n / 2 + 1;
	for(j = 0;j < n;j++){
		putchar('*');
	}
	putchar('\n');
	for(i = 1;i < h;i++){
		for(j = 0;j < n - i - 1;j++){
			if(j < i)putchar(' ');
			else if(j == i)putchar('*');
			else{
				putchar(i <= m?' ':'*');
			}
		}
		putchar('*');putchar('\n');
	}
	for(i = 1;i < h;i++){
		for(j = 0;j < (n % 2 == 0?h + i - 1:h + i - 2);j++){
			if(i + j < h)putchar(' ');
			else if(i + j == h)putchar('*');
			else{
				putchar(i < h - m?' ':'*');
			}
		}
		putchar('*');putchar('\n');
	}
	for(j = 0;j < n;j++){
		putchar('*');
	}
	putchar('\n');
}

F 电梯

题意是A坐电梯去找B.后面有比较大的数据 模拟会超时

第一种解法:

  • 如果A和B在同一层,结论显然.
  • 考虑循环 如果有\(m\)层,循环节长度是\(2m-2\) 利用取mod可以确定当前状态.
  • 先考虑A坐上电梯有3种情况
  • A找B 有4种情况 分别处理即可(各位可以想想是哪些情况)
#include <stdio.h>
int main(){
	int m,s,t,n,ans = 0;
	scanf("%d%d%d%d",&m,&s,&t,&n);
	int loop = 2 * m - 2;//电梯循环周期
	int current = n % loop + 1;//电梯在第n秒的位置
	if(s == t){//AB同一层
		ans = n;
	}
	else{
		if(current <= s){//电梯向上运动能接到A
			;
		}
		else if(current > s && current <= (loop + 2 - s)){//电梯向下运动能接到A
			s = loop + 2 - s;
		}
		else{//这趟不行 下一趟电梯向上运动能接到A
			s += loop;
		}

		//4种情况
		if(s <= t){
			;
		}
		else if(s <= (2 * m - t)){
			t = loop + 2 - t;
		}
		else if(s <= (2 * m + t)){
			t += loop;
		}
		else{
			t = 2 * loop + 2 - t;
		}
		ans = n + (t - current);
	}
	printf("%d",ans);
	return 0;
}

另解:

(这个是我搬运出题julao给的做法 原理他写在注释里了)

#include <stdio.h>
#include <math.h>

long long n,maxv,s,t,n,mm;
int main(){
	scanf("%lld",&maxv);
	mm=(maxv-1)*2;//电梯上下一个周期的时间
	scanf("%lld %lld %lld",&s,&t,&n);
	if(s==t){
	    printf("%lld\n",n);//小迷弟那都不用去直接到包房
	}
    else{
    	long long tmp1,tmp2;
    	if(s<t) tmp1=s-1;//电梯从1楼向上接到小迷弟
    	else tmp1=mm+1-s;//电梯从maxv层向下接到小迷弟
    	long long tmp3=n/mm*mm+tmp1;//n秒之前电梯跑过n/mm*mm次轮回 又花了tmp1的时间接小迷弟
		if(tmp3<n) tmp2=tmp3+mm;//但是仍有可能小于n 如果小于n必须加个周期才能保证在小迷弟出现之后接到小迷弟
		else tmp2=tmp3;
		printf("%lld\n",tmp2+abs(s-t));//再走两者的距离
    }
  	return 0;
}

G

  • 很容易漏掉'0'
  • 下面给2种做法
    最朴素的办法是 分 情 况 一 个 个 列
    为了增强代码可读性 建议不要照着下面的来
    65你就写成'A'是可以的
#include <stdio.h>
int main(){

	for(;;){
		char ch = getchar();
		if(ch == -1)break;
		if(!(ch >= 0x20 && ch < 0x7f))continue;//处理掉特殊字符
		if(ch == '1')
			printf("1");
		else if(ch == '2')
			printf("2");
		else if(ch == '3')
			printf("3");
		else if(ch == '4')
			printf("4");
		else if(ch == '5')
			printf("5");
		else if(ch == '6')
			printf("6");
		else if(ch == '7')
			printf("7");
		else if(ch == '8')
			printf("8");
		else if(ch == '9')
			printf("9");
		else if(ch == '0')
			printf("0");
		else if((ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122)){
			if((ch >= 65 && ch <= 67) || (ch >= 97 && ch <= 99))
				printf("2");
			else if((ch >= 68 && ch <= 70) || (ch >= 100 && ch <= 102))
				printf("3");
			else if((ch >= 71 && ch <= 73) || (ch >= 103 && ch <= 105))
				printf("4");
			else if((ch >= 74 && ch <= 76) || (ch >= 106 && ch <= 108))
				printf("5");
			else if((ch >= 77 && ch <= 79) || (ch >= 109 && ch <= 111))
				printf("6");
			else if((ch >= 80 && ch <= 83) || (ch >= 112 && ch <= 115))
				printf("7");
			else if((ch >= 84 && ch <= 86) || (ch >= 116 && ch <= 118))
				printf("8");
			else if((ch >= 87 && ch <= 90) || (ch >= 119 && ch <= 122))
				printf("9");
		}
		else printf("1");
	}
	return 0;
}

当然为了省事 这样也可
注意包含ctype.h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <time.h>
int ch2key[30] = {2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9};
int main(){
	for(;;){
		char ch = getchar();
		if(ch == EOF){
			break;
		}
		else{
			if(isdigit(ch)){
				putchar(ch);
			}
			else if(islower(ch)){
				ch = toupper(ch);
				putchar('0' + (ch2key[ch - 'A']));
			}
			else if(isupper(ch)){
				putchar('0' + (ch2key[ch - 'A']));
			}
			else if(isprint(ch)){
				putchar('1');
			}
		}
	}
	return 0;
}

H 小兔子乖乖拔萝卜

  • 思路是维护最大的3个数 需要注意更新数据时的操作顺序
  • 来一组数据处理一组输出一次 不用纠结处理完所有的一次输出
#include<stdio.h>
int main()
{
	int num,max1=0,max2=0,max3=0,t;
	while(scanf("%d",&num) != EOF){
		int n;
		for(n=1;n<=num;n++){
			scanf("%d",&t);
			if(t>=max1) {
				max3=max2;
				max2=max1;
				max1=t;
			}
			if( (t>=max2) && (t<max1) ){
				max3=max2;
				max2=t;
			}
			if( (t>=max3) && (t<max2) ) max3=t;
		}
		printf("%d %d %d\n",max1,max2,max3);
	}
	return 0;
}
  • 各位可以想下 如果他给了long long也装不下的巨大整数 该怎么办

I 多边形对角线

  • 注意数据范围和long long的使用方式
  • 其实是数学问题
    • 注意任意3条对角线不相交
    • 每个交点必然是由2条对角线相交得到的.每条对角线对应2个顶点
    • 问题转化成从n个点里面选4个不同点
#include <stdio.h>
int main(){
	long long n;
	scanf("%lld",&n);
	printf("%lld",n*(n-1)*(n-2)*(n-3)/24);
	return 0;
}

J 朵朵选靓号

  • 可以开字符数组做,也可以用long long提取每一位做
    参考代码:
#include<stdio.h>
int main(){
 char a[20];
 int i,f=0,h=0;i=0;
	fgets(a,15,stdin);
	for(i=0;i<=10;i++){
		if(a[i]=='5')f++;
 		if(a[i]=='2'&&a[i+1]=='3'&&a[i+2]=='3')h=1;
 	}
 	if(h==1&&f<3)printf("Wonderful:%d",f);
 	else if(h==0)printf("Not good:%d",f);
 	else printf("Great:%d",f);
 	return 0;
}

尾声:

image

posted @ 2021-03-17 13:55  仪光19暴毙开发者  阅读(136)  评论(0编辑  收藏  举报