acm寒假训练第一周总结

一:实训相关

  1. 时间:2022.1.11-2022.1.16
  2. 内容:模拟与高精度题单。
  3. 实训详情:完成8道,未通过2道,剩余4道。平均每题耗时1h。

二:题目记录

1.P1042[NOIP2003 普及组] 乒乓球,该题主要为遍历判断字符串内容,以及在题意中的含义,最后进行记录并得出结果。

题目源码:

#include <stdio.h>
#include<string.h>
int main(void)
{
    char a[100000];
    int l,i=0,flag=1,m=0,n=0;//m计数华华得分,n计数对手得分
    while(flag==1)
    {
        scanf("%c",&a[i]);
        if(a[i]=='E')
            flag=0;
        i++;
    }
    l=strlen(a);
    for(i=0;i<l;i++)
    {
        if(a[i]=='W')
            m++;
        if(a[i]=='L')
            n++;
        if(a[i]=='\r')//如果遇到换行,结束本次循环
            continue;
        //计算够不够11回合并且还得得分大于等于2
        if((m>=11||n>=11)&&(n-m>=2||m-n>=2))
        {
            printf("%d:%d\n",m,n);
            m=0,n=0;
        }
        if(i==l-1)
            printf("%d:%d\n",m,n);//不够11回合的输出
    }
    printf("\n");
    m=0,n=0;
    for(i=0;i<l;i++)
    {
        if(a[i]=='W')
            m++;
        if(a[i]=='L')
            n++;
        if(a[i]=='\r')
            continue;
        if((m>=21||n>=21)&&(n-m>=2||m-n>=2))
        {
            printf("%d:%d\n",m,n);
            m=0,n=0;
        }
        if(i==l-1)
            printf("%d:%d\n",m,n);//不够21回合的输出
    }
    return 0;
}

2.P2670[NOIP2015 普及组] 扫雷游戏,该题可以通过判断目标八个方向的状态在达到题目要求。

题目源码:

#include <stdio.h>
int n, m, t = 0;
char a[101][101];
char b[101][101];

int main() {
	scanf("%d %d", &n, &m);
	for (int i = 0; i < n; i++)
		scanf("%s", a[i]);
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++)
         {
			if (a[i][j] == '*')
				b[i][j] = '*';
			else 
              {
				t = 0;
				if (a[i][j + 1] == '*')
					t++;
				if (a[i][j - 1] == '*')
					t++;
				if (a[i - 1][j] == '*')
					t++;
				if (a[i + 1][j] == '*')
					t++;
				if (a[i - 1][j - 1] == '*')
					t++;
				if (a[i + 1][j - 1] == '*')
					t++;
				if (a[i - 1][j + 1] == '*')
					t++;
				if (a[i + 1][j + 1] == '*')
					t++;
				b[i][j] = t + '0';
			}
		}
	}

	for (int i = 0; i < n; i++)
		printf("%s\n", b[i]);
    return 0;
}

P1563[NOIP2016 提高组] 玩具谜题,该题难度挺大,在于执行命令时由于每个小人的站位的方向不同,导致顺逆时针的判断容易出错,经过参考大佬题解并综合修改得出判断四种情况,并且调整超出规定的值,便终于得到答案

题目源码:

#include <stdio.h>
#include <string.h>
struct person {
	int d;//direction
	char job[10];
};
int a[1000000][2];//order
int n, m, k = 0; //k is goal
struct person s[1000000];
int main() {
	scanf("%d%d", &n, &m);
	for (int i = 0; i < n; i++)
		scanf("%d %s", &s[i].d, s[i].job);
	for (int i = 0; i < m; i++)
		scanf("%d %d", &a[i][0], &a[i][1]);
	for (int i = 0; i < m; i++) {
		if (s[k].d == 0) {
			//inside
			if (a[i][0] == 0) //inside left
				k = (k + n - a[i][1]) % n;
			else if (a[i][0] == 1) //inside right
				k = (k + a[i][1]) % n;

		} else if (s[k].d == 1) {
			//outside
			if (a[i][0] == 0) //outide left
				k = (k + a[i][1]) % n;
			else if (a[i][0] == 1) //outide right
				k = (k + n - a[i][1]) % n;
		}
	}
	printf("%s", s[k].job);
	return 0;
}

P1601A+B Problem(高精)与P1303A*B Problem为同类型,在于用字符串数组输入数据,并且逆序保存其整型数值于数组,再模拟竖式一一计算,进位问题同时也需特别注意。

题目源码:

//a+b
#include <stdio.h>
#include <string.h>
char a[1000000], b[1000000], t, t1, j, max = 0, temp, temp1;
int c[1000000];

int main() {
	scanf("%s%s", a, b);
	int i, j;
	t = strlen(a);
	t1 = strlen(b);

	for (int i = 0; i < t / 2; i++) {
		temp = a[i];
		a[i] = a[t - 1 - i];
		a[t - 1 - i] = temp;
	}

	for (int i = 0; i < t1 / 2; i++) {
		temp1 = b[i];
		b[i] = b[t1 - 1 - i];
		b[t1 - 1 - i] = temp1;
	}

	for (int i = 0; i < t; i++)
		a[i] = a[i] - 48 ;

	for (int i = 0; i < t1; i++)
		b[i] = b[i] - 48;

	max = t > t1 ? (t + 1 ) : (t1 + 1);


	for (int i = 0; i < max; i++) {
		c[i] += a[i] + b[i];
		c[i + 1] = c[i] / 10;
		c[i] = c[i] % 10;
	}

	if (c[max - 1] == 0)
		max--;

	for (int i = max - 1; i >= 0; i--)
		printf("%d", c[i]);

}
//a*b
#include <stdio.h>
#include <string.h>
char a[1000000], b[1000000], temp, temp1;
int c[1000000], t, t1;

int main() {
	scanf("%s%s", a, b);
	int i, j;
	t = strlen(a);
	t1 = strlen(b);
	int t2;
	t2 = t + t1;

	for (int i = 0; i < t / 2; i++) {
		temp = a[i];
		a[i] = a[t - 1 - i];
		a[t - 1 - i] = temp;
	}

	for (int i = 0; i < t1 / 2; i++) {
		temp1 = b[i];
		b[i] = b[t1 - 1 - i];
		b[t1 - 1 - i] = temp1;
	}

	for (int i = 0; i < t; i++)
		a[i] = a[i] - 48 ;

	for (int i = 0; i < t1; i++)
		b[i] = b[i] - 48;

	for (int i = 0; i < t; i++) {
		for (int j = 0; j < t1; j++) {
			c[i + j] += a[i] * b[j];
			c[i + j + 1] += c[i + j] / 10;
			c[i + j] %= 10;

		}
	}
	t2 -= 1;
	while (c[t2] == 0 && t2 > 0)
		t2--;
	for (int i = t2; i >= 0; i--)
		printf("%d", c[i]);
	return 0;



}


P1328[NOIP2014 提高组] 生活大爆炸版石头剪刀布,该题可以列举所有的情况暴力解题,能ac的代码就是好代码

题目源码:

#include <stdio.h>
int panduan(int x, int y);

int main() {
	int N, N1, N2, w, n1 = 0, n2 = 0, j = 0, k = 0;
	scanf("%d %d %d", &N, &N1, &N2);
	int a[1000], b[1000];
	for (int i = 0; i < N1; i++)
		scanf("%d", &a[i]);
	for (int i = 0; i < N2; i++)
		scanf("%d", &b[i]);
	for (int i = 0; i < N; i++) {
		if (j >= N1)
			j = 0;

		if (k >= N2)
			k = 0;

		w = panduan(a[j], b[k]);
	

		if (w == 0);

		else if (w == 1)
			n1++;
		else if (w == -1)
			n2++;


		j++;
		k++;
	}

	printf("%d %d", n1, n2);
}

int panduan(int x, int y) {
	if (x == y)
		return 0;//平局
	if ((x == 0 && y == 2) || (x == 0 && y == 3))
		return 1;
	if ((x == 0 && y == 1) || (x == 0 && y == 4))
		return -1;
	if ((x == 1 && y == 0) || (x == 1 && y == 3))
		return 1;
	if ((x == 1 && y == 2) || (x == 1 && y == 4))
		return -1;
	if ((x == 2 && y == 1) || (x == 2 && y == 4))
		return 1;
	if ((x == 2 && y == 0) || (x == 2 && y == 3))
		return -1;
	if ((x == 3 && y == 4) || (x == 3 && y == 2))
		return 1;
	if ((x == 3 && y == 1) || (x == 3 && y == 0))
		return -1;
	if ((x == 4 && y == 0) || (x == 4 && y == 1))
		return 1;
	if ((x == 4 && y == 2) || (x == 4 && y == 3))
		return -1;
}

P1067[NOIP2009 普及组] 多项式输出,本题细节特别多且容易忘记,以至于我写了许久才得到ac代码,参考了大佬的题解后进行特判第一项和最后两项得以简化原有代码,并修改错误。

题目源码:

#include <stdio.h>
#include <math.h>
int a[1000];
int main() {
	int n, k = 0;
	scanf("%d", &n);
	for (int i = 0; i <= n; i++)
		scanf("%d", &a[i]);
	for (int i = 0; i <= n - 2; i++) {
		if (i >= 1 && a[i] > 0)
			printf("+");
		if (a[i] != 0 && a[i] != 1 && a[i] != -1)
			printf("%dx^%d", a[i], n - i);
		if (a[i] == 1)
			printf("x^%d", n - i);
		if (a[i] == -1)
			printf("-x^%d", n - i);
	}
	if (a[n - 1] != 0) {
		if (a[n - 1] < 0) {
		
			if (a[n - 1] != -1)
				printf("%dx", a[n - 1]);
			if (a[n - 1] == -1)
				printf("-x");
		}
		if (a[n - 1] > 0) {
		
			if (a[n - 1] != 1)
				printf("+%dx", a[n - 1]);
			if (a[n - 1] == 1)
				printf("+x");
		}
	}
	if (a[n] != 0) {

		if (a[n] > 0)
			printf("+%d", a[n]);
		else
			printf("%d", a[n]);
	}
	return 0;
}

P1098[NOIP2007 提高组] 字符串的展开,本题需仔细推敲题目情况,将情况一一列举并注意细节,便能ac

题目源码:

#include <stdio.h>
#include <string.h>
char a[110];

int pangduan(int x, int y) {
	int t = 0;

	if ((x >= 97 && x <= 122) && (y >= 97 && y <= 122))
		t++;
	else if ((x >= 48 && x <= 57) && (y >= 48 && y <= 57))
		t++;

	return t;

}

int main() {
	int p1, p2, p3, t, w;
	scanf("%d%d%d", &p1, &p2, &p3);
	scanf("%s", a);
	t = strlen(a);

	for (int i = 0; i < t; i++) {
		if (a[i] == '-') {

			w = pangduan(a[i - 1], a[i + 1]);


			if (a[i - 1] < a[i + 1] && a[i - 1] != a[i + 1] - 1 && w == 1) {
				//first
				if ((a[i - 1] >= 97 && a[i - 1] <= 122) && (a[i + 1] >= 97 && a[i + 1] <= 122)) {
					//letter
					switch (p1) {
						case 1: {
							if (p3 == 1) { //order
								for (int j = a[i - 1] + 1; j < a[i + 1]; j++) {
									for (int i = 0; i < p2; i++)
										printf("%c", j);

								}
							} else if (p3 == 2) { // reverse
								for (int j = a[i + 1] - 1; j > a[i - 1]; j--)
									for (int i = 0; i < p2; i++)
										printf("%c", j);
							}
						}
						break;

						case 2: {
							if (p3 == 1) {
								//order
								for (int j = a[i - 1] + 1; j < a[i + 1]; j++) {
									for (int i = 0; i < p2; i++)
										printf("%c", j - 32);

								}
							} else if (p3 == 2) { // reverse
								for (int j = a[i + 1] - 1; j > a[i - 1]; j--) {
									for (int i = 0; i < p2; i++)
										printf("%c", j - 32);
								}
							}

						}
						break;

						case 3: {
							for (int j = a[i - 1] + 1; j < a[i + 1]; j++)
								for (int i = 0; i < p2; i++)
									printf("*");
						}
						break;
					}
				}

				else if ((a[i - 1] >= 48 && a[i - 1] <= 71) && (a[i + 1] >= 48 && a[i + 1] <= 71)) {
					//number
					if (p1 != 3) {
						for (int j = a[i - 1] + 1 - 48; j < a[i + 1] - 48; j++) {
							for (int i = 0; i < p2; i++)
								printf("%d", j);

						}
					} else if (p1 == 3) {
						for (int j = a[i - 1] + 1 - 48; j < a[i + 1] - 48; j++)
							for (int i = 0; i < p2; i++)
								printf("*");
					}
				}
			} else if (a[i + 1] == a[i - 1] + 1)
				printf("");
			else if (a[i + 1] <= a[i - 1] || w == 0)
				printf("-");
		} else
			printf("%c", a[i]);
	}

}

三:个人总结

  • 做题笔记
  1. 高精度进行计算时,需先用字符数组存储数据,方便利用gets进行输入,与得到输入长度。再者将其逆序保存其整型数据到数组中,最后进行计算。
  2. 在题目要求结果保留n位有效数字的条件下,可以通过printf(“%.ng”,x)。
  • 实际总结
  1. 经过有计划地训练一周,可以明显地感觉到思维的高度有了些微的上升,虽然面对一些我目前的难题,还是略显不足,但总归还是前进了一点。
  2. 在对于之前少遇的高精度、字符串难题,有了些自己的见解,与思考方法,是难得的进步。
  3. 再者,对于以往急躁的性格与粗心的做题习惯,也有了不一般的改变。

上一篇:Net6 DI源码分析Part2 Engine,ServiceProvider


下一篇:dubbo之服务本地暴露