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