2021算法笔记Codeup、pat刷题记录
目录
- 《算法笔记》2.1小节——C/C++快速入门->基本数据类型
- 《算法笔记》2.2小节——C/C++快速入门->顺序结构
- 《算法笔记》2.3小节——C/C++快速入门->选择结构
- 《算法笔记》2.4小节——C/C++快速入门->循环结构
- 《算法笔记》2.5小节——C/C++快速入门->数组
- 《算法笔记》2.6小节——C/C++快速入门->函数
- 《算法笔记》2.7小节——C/C++快速入门->指针
- 《算法笔记》2.8小节——C/C++快速入门->结构体(struct)的使用
- 《算法笔记》2.9小节——C/C++快速入门->补充
- 《算法笔记》2.10小节——C/C++快速入门->黑盒测试
- 《算法笔记》3.1小节——入门模拟->简单模拟
- 《算法笔记》3.2小节——入门模拟->查找元素
- 《算法笔记》3.3小节——入门模拟->图形输出
- 《算法笔记》3.4小节——入门模拟->日期处理
- 《算法笔记》3.5小节——入门模拟->进制转换
- 《算法笔记》3.6小节——入门模拟->字符串处理
- 《算法笔记》4.1小节——算法初步->排序
- 《算法笔记》4.2小节——算法初步->哈希
- 《算法笔记》4.3小节——算法初步->递归
- 《算法笔记》4.4小节——算法初步->贪心
- 《算法笔记》4.5小节——算法初步->二分
- 《算法笔记》4.6小节——算法初步->two pointers
- 《算法笔记》4.7小节——算法初步->其他高效技巧与算法
《算法笔记》2.1小节——C/C++快速入门->基本数据类型
重点:
- 不要使用float,碰到浮点型的数据都使用double;
- 小写字母比大写字母的ASCII码值大32;
- INF设置为(1<<31)-1;(一般更常用(1 << 30)-1因为可以避免相加超过int的情况);
《算法笔记》2.2小节——C/C++快速入门->顺序结构
重点:
math.h
:绝对值fab(double x)
、向下和取整向上取整floor(double x)
和ceil(double x)
、算术平方根sqrt(double x)
、四舍五入round(double x)
例题1-1-1 按要求输出信息(1)
#include<stdio.h>
int main(){
printf("This is my first c program!");
return 0;
}
例题1-1-2 按要求输出信息(2)
#include<stdio.h>
int main() {
printf("********************\nVery Good!\n********************");
return 0;
}
例题1-2-1 求两个整数之和(1)
#include<stdio.h>
int main() {
int a, b, sum;
a = 123;
b = 456;
sum = a + b;
printf("sum=%d", sum);
return 0;
}
例题1-2-2 求两整数数之和(2)
#include<stdio.h>
int main() {
int a, b;
scanf("%d %d", &a, &b);
printf("%d", a + b);
}
例题3-5 求一元二次方程的根
#include<stdio.h>
#include<math.h>
int main() {
double a, b, c;
scanf("%lf %lf %lf", &a, &b, &c);
double delta = pow(b, 2) - 4 * a * c;
printf("r1=%7.2f\nr2=%7.2f", (-b + sqrt(delta)) / (2 * a), (-b - sqrt(delta)) / (2 * a));
return 0;
}
例题3-9 字符输入输出
#include<stdio.h>
int main() {
char str[4];
scanf("%s", str);
printf("%s", str);
}
《算法笔记》2.3小节——C/C++快速入门->选择结构
例题4-1 一元二次方程求根
#include<stdio.h>
#include<math.h>
int main() {
double a, b, c;
scanf("%lf %lf %lf", &a, &b, &c);
double delta = pow(b, 2) - 4 * a * c;
if (delta < 0) printf("No real roots!");
else
printf("r1=%7.2f\nr2=%7.2f", (-b + sqrt(delta)) / (2 * a), (-b - sqrt(delta)) / (2 * a));
return 0;
}
例题4-2 比较交换实数值
#include<stdio.h>
const double eps=1e-8;
#define More(a,b) (((a)-(b))>(eps))
int main() {
double a, b;
scanf("%lf %lf", &a, &b);
if (More(a, b)) printf("%.2f %.2f", b, a);
else printf("%.2f %.2f", a, b);
}
例题4-3 比较交换3个实数值,并按序输出
#include<stdio.h>
void swap(double& x, double& y);
const double eps = 1e-8;
#define More(a,b) (((a)-(b))>(eps))
int main() {
double a, b, c;
scanf("%lf %lf %lf", &a, &b, &c);
if (More(x, y)) swap(x, y);
if (More(y, z)) swap(y, z);
if (More(x, y)) swap(x, y);
printf("%.2f %.2f %.2f", a, b, c);
}
void swap(double& x, double& y) {
double temp = x;
x = y;
y = temp;
}
习题4-4 三个整数求最大值
#include<stdio.h>
#define INF ((1 << 30)-1)
int main() {
int a, b, c, max = -INF;
scanf("%d %d %d", &a, &b, &c);
if (a > b && a > c) max = a;
else if (b > a && b > c) max = b;
else max = c;
printf("%d\n", max);
return 0;
}
习题4-10-1 奖金计算
#include<stdio.h>
int main() {
double profit,award;
scanf("%lf", &profit);
if (profit <= 100000) {
award = profit * 0.1;
}
else if (profit <= 200000) {
award = 10000 + 0.075 * (profit - 100000);
}
else if (profit <= 400000) {
award = 17500 + 0.05 * (profit - 200000);
}
else if (profit <= 600000) {
award = 27500 + 0.03 * (profit - 400000);
}
else if (profit <= 1000000) {
award = 33500 + 0.015 * (profit - 600000);
}
else {
award = 39500 + 0.01 * (profit - 1000000);
}
printf("%.2f", award);
return 0;
}
《算法笔记》2.4小节——C/C++快速入门->循环结构
例题5-1-1 连续自然数求和
#include<stdio.h>
int main() {
int i = 1,sum = 0;
while (i <= 100) {
sum += i;
++i;
}
printf("%d", sum);
return 0;
}
例题5-1-2 连续自然数求和
#include<stdio.h>
int main() {
int i = 1,sum = 0;
do{
sum += i;
++i;
} while (i <= 100);
printf("%d", sum);
return 0;
}
例题5-1-3 连续自然数求和
#include<stdio.h>
int main() {
int sum = 0;
for (int i = 1;i <= 100;++i) {
sum += i;
}
printf("%d", sum);
return 0;
}
例题5-1-4 连续自然数求和
#include<stdio.h>
int main() {
int n, sum = 0;
scanf("%d", &n);
for (int i = 1;true;++i) {
sum += i;
if (i >= n) break;
}
printf("%d", sum);
return 0;
}
例题5-1-5 连续自然数求和
#include<stdio.h>
int main() {
int i = 1,sum = 0;
for (;sum < 1000;++i) sum += i;
printf("%d", i - 1);
return 0;
}
例题5-6 矩阵输出
#include<stdio.h>
int main() {
for (int i = 1;i < 5;++i) {
for (int j = 1;j < 6;++j) {
printf("%3d", j * i);
}
printf("\n");
}
return 0;
}
例题5-7 求圆周率pi的近似值
#include<stdio.h>
const double min = 1e-6;
int main() {
double qpi = 0;
int flag = 1;
for (int i = 1;1.0 / i >= min;i += 2, flag /= -1)
qpi += 1.0 / i * flag;
printf("PI=%10.8f\n", 4.0 * qpi);
return 0;
}
例题5-8 Fibonacci数列
#include<stdio.h>
int main() {
int n, n1 = 1, n2 = 1;
scanf("%d", &n);
for (int i = 3;i <= n;++i) {
int res = n1 + n2;
n1 = n2;
n2 = res;
}
printf("%d\n", n2);
return 0;
}
习题5-10 分数序列求和
#include<stdio.h>
int main() {
double a = 1, b = 2, sum = 0;
for (int i = 0;i < 20;++i) {
sum += b / a;
double temp = a + b;
a = b;
b = temp;
}
printf("%.6f\n", sum);
return 0;
}
《算法笔记》2.5小节——C/C++快速入门->数组
重点:
- 数组大小较大(大概106级别),则需要定义在主函数外面;
memset(数组名,值,sizeof(数组名));
注意:memset 使用按字节赋值,因此只使用来赋值-1或0;如果要赋其他数字使用fill函数(但memset的知执行速度快);gets
和puts
会导致Codeup编译失败;sscanf(str, "%d", &n);
类比于scanf(screen, "%d", &n);
(左->右)
sprintf(str , "%d", n);
类比于printf(screen, "%d", n);
(右->左)
习题6-4 有序插入
#include<stdio.h>
int main() {
int a[10];
for (int i = 0;i < 9;++i) {
scanf("%d", &a[i]);
}
int temp,i;
scanf("%d", &temp);
for (i = 8;a[i] > temp;--i) {
a[i + 1] = a[i];
}
a[i + 1] = temp;
for (int i = 0;i < 10;++i) {
printf("%d\n", a[i]);
}
return 0;
}
习题6-5 数组元素逆置
#include<stdio.h>
int main() {
int a[10];
for (int i = 0;i < 10;++i) {
scanf("%d", &a[9-i]);//反向输入,耍小聪明
}
for (int i = 0;i < 10;++i) {
printf("%d\n", a[i]);
}
return 0;
}
习题6-6 杨辉三角
#include<stdio.h>
int main() {
int a[10][10] = { 0 }, n;
a[0][0] = 1;
for (int i = 0;i < 10;++i) {
for (int j = 1;j < 10;++j) {
if (i == 0 || (i == 9 && j == 9)) a[j][i] = 1;
else a[j][i] = a[j - 1][i - 1] + a[j - 1][i];
}
}
scanf("%d", &n);
for (int i = 0;i < n;++i) {
for (int j = 0;j < 10;++j) {
if (a[i][j] != 0) {
if (j != 0) printf(" ");
printf("%d", a[i][j]);
}
}
printf("\n");
}
return 0;
}
习题6-12 解密
#include<stdio.h>
int main() {
char str[100];
scanf("%s",str);//不知为何codeup不让使用gets puts(产生编译错误)
for (int i = 0;i < 100 && str[i] != '\0';++i) {
if (str[i] >= 'a' && str[i] <= 'z') {
str[i] = 'z' - str[i] + 'a';
}
else if (str[i] >= 'A' && str[i] <= 'Z') {
str[i] = 'Z' - str[i] + 'A';
}
}
printf("%s",str);
return 0;
}
习题6-13 字符串比较
#include<stdio.h>
int main() {
char a[100], b[100];
scanf("%s", a);//本题要求使用gets,但使用gets时会编译错误
scanf("%s", b);
int i;
for (i = 0;a[i] == b[i];++i);
printf("%d", a[i] - b[i]);
return 0;
}
例题6-1 逆序输出数组元素
#include<stdio.h>
int main() {
int a[10];
for (int i = 0;i < 10;++i) {
scanf("%d", a+9-i);//不知道为什么同样的题目用相同的代码
} //一次过了一次编译错误。。。
for (int i = 0;i < 10;++i) {
printf("%d\n", a[i]);
}
return 0;
}
例题6-2 数组求解Fibonacci数列问题
#include<stdio.h>
int main() {
int a[20] = { 1,1 };
for (int i = 2;i < 20;++i) a[i] = a[i - 2] + a[i - 1];
for (int i = 0;i < 20;++i) printf("%d\n", a[i]);
return 0;
}
例题6-3 冒泡排序
#include<stdio.h>
int main() {
int a[10] = { 0 };
for (int i = 0;i < 10;++i) scanf("%d", a + i);
for (int i = 0;i < 10;++i) {
for (int j = 1;j < 10 - i;++j) {
if (a[j] < a[j - 1]) {
int temp = a[j];
a[j] = a[j - 1];
a[j - 1] = temp;
}
}
}
for (int i = 0;i < 10;++i) printf("%d\n", a[i]);
return 0;
}
例题6-4 矩阵转置
#include<stdio.h>
int main() {
int a[2][3], b[3][2];
for (int i = 0;i < 2;++i)
for (int j = 0;j < 3;++j)
scanf("%d", &a[i][j]);
for (int i = 0;i < 2;++i)
for (int j = 0;j < 3;++j)
b[j][i] = a[i][j];
for (int i = 0;i < 3;++i) {
for (int j = 0;j < 2;++j) {
if (j) printf(" ");
printf("%d", b[i][j]);
}
printf("\n");
}
return 0;
}
#include<stdio.h>
#include<cstring>
int main() {
char a[10], b[10], c[10];
scanf("%s", a);
scanf("%s", b);
scanf("%s", c);
if (strcmp(a, b) > 0)
if (strcmp(a, c) > 0) printf("%s", a);
else printf("%s", c);
else
if (strcmp(b, c) > 0) printf("%s", b);
else printf("%s", c);
return 0;
}
《算法笔记》2.6小节——C/C++快速入门->函数
习题7-5 字符串逆序存放
#include<stdio.h>
#include<cstring>
void invert(char str[]);
int main() {
char str[20];
scanf("%s", str);
invert(str);
return 0;
}
void invert(char str[]) {
char temp[20];
for (int i = 0;i < strlen(str);++i) {
temp[i] = str[strlen(str) - i - 1];
}
temp[strlen(str)] = NULL;
printf("%s", temp);
}
习题7-7 复制字符串中的元音字母
#include<stdio.h>
#include<cstring>
void GetVowel(char str[]);
int main() {
char str[20];
scanf("%s", str);
GetVowel(str);
return 0;
}
void GetVowel(char str[]) {
char Vowel[20];
int cnt = 0;
for (int i = 0;i < strlen(str);++i) {
if (str[i] == 'a' || str[i] == 'e' || str[i] == 'i' || str[i] == 'o' || str[i] == 'u' ||
str[i] == 'A' || str[i] == 'E' || str[i] == 'I' || str[i] == 'O' || str[i] == 'U') {
Vowel[cnt++] = str[i];
}
}
Vowel[cnt] = NULL;
printf("%s", Vowel);
}
《算法笔记》2.7小节——C/C++快速入门->指针
C语言10.1
#include<stdio.h>
int main() {
int a, b;
int* q = &a, * p = &b;
scanf("%d %d", &a, &b);
if (*p > *q) q = &b, p = &a;
printf("%d %d", *q, *p);
return 0;
}
C语言10.2
#include<stdio.h>
void compare(int*& q, int*& p);
int main() {
int a, b, c;
int* q = &a, * p = &b, * k = &c;
scanf("%d %d %d", &a, &b, &c);
compare(q, p);
compare(p, k);
compare(q, p);
printf("%d %d %d", *q, *p, *k);
return 0;
}
void compare(int*& q, int*& p) {
if (*p > *q) {
int* temp = q;
q = p;
p = temp;
}
}
C语言10.10
#include<stdio.h>
int main() {
char str[] = { "I love China!" };
char* a = str;
int n;
scanf("%d", &n);
printf("%s", a + n);
return 0;
}
C语言10.15
#include<stdio.h>
#include<cstring>
void swap(char*& p, char*& q);
int main() {
char str1[20], str2[20], str3[20];
scanf("%s", str1);
scanf("%s", str2);
scanf("%s", str3);
char* p1 = str1, * p2 = str2, * p3 = str3;
if (strcmp(p1, p2) > 0) swap(p1, p2);
if (strcmp(p2, p3) > 0) swap(p2, p3);
if (strcmp(p1, p2) > 0) swap(p1, p2);
printf("%s\n%s\n%s\n", p1, p2, p3);
return 0;
}
void swap(char*& p, char*& q) {
char* temp = p;
p = q;
q = temp;
}
C语言10.16
#include<stdio.h>
#include<cstring>
void scanf10num(int a[]);
void swapmaxmin(int a[]);
void print10num(int a[]);
int main() {
int a[10];
scanf10num(a);
swapmaxmin(a);
print10num(a);
return 0;
}
void scanf10num(int a[]) {
for (int i = 0;i < 10;++i) {
scanf("%d", a + i);
}
}
void swapmaxmin(int a[]) {
int minq = 0, maxq = 0, max = -1, min = (1 << 30) - 1;
for (int i = 0;i < 10;++i) {
if (a[i] > max) {
max = a[i];
maxq = i;
}
if (a[i] < min) {
min = a[i];
minq = i;
}
}
a[maxq] = a[9];
a[9] = max;
a[minq] = a[0];
a[0] = min;
}
void print10num(int a[]) {
for (int i = 0;i < 10;++i) {
printf("%d ", a[i]);
}
printf("\n");
}
《算法笔记》2.8小节——C/C++快速入门->结构体(struct)的使用
重点:
构造函数的两种形式:
studentInfo(int _id, char _gender): id(_id), gender(_gender) {}
studentInfo(int _id, char _gender){
id = _id;
gender = _gender;
}
C语言11.1
#include<stdio.h>
#include<cstring>
struct candidate {
char name[20];
int count;
}leader[3] = { "Li",0 ,"Zhang",0,"Fun",0 };
int main() {
int n;
scanf("%d", &n);
for (int i = 0;i < n;++i) {
char str[20];
scanf("%s", str);
for (int j = 0;j < 3;++j) {
if (!strcmp(leader[j].name, str)) ++leader[j].count;
}
}
for (int i = 0;i < 3;++i) {
printf("%s:%d\n", leader[i].name, leader[i].count);
}
return 0;
}
C语言11.2
#include<stdio.h>
#include<cstring>
struct student {
int num;
char name[20];
char sex;
int age;
}stu[10];
int main() {
int n;
student* p;
scanf("%d", &n);
for (int i = 0;i < n;++i) {
p = &stu[i];
scanf("%d %s %c %d", &(p->num), &(p->name), &(p->sex), &(p->age));
}
for (int i = 0;i < n;++i) {
p = &stu[i];
printf("%d %s %c %d\n", p->num, p->name, p->sex, p->age);
}
return 0;
}
C语言11.4
#include<stdio.h>
#include<cstring>
struct {
int num;
char name[10];
char sex;
char job;
union {
int classes;
char position[10];
}category;
}person[10];
int main() {
int n;
scanf("%d", &n);
for (int i = 0;i < n;++i) {
scanf("%d %s %c %c ",&person[i].num,person[i].name,&person[i].sex,&person[i].job);
if (person[i].job == 's') scanf("%d", &person[i].category.classes);
else scanf("%s", &person[i].category.position);
}
for (int i = 0;i < n;++i) {
printf("%d %s %c %c ", person[i].num, person[i].name, person[i].sex, person[i].job);
if (person[i].job == 's') printf("%d\n", person[i].category.classes);
else printf("%s\n", person[i].category.position);
}
return 0;
}
C语言11.7
#include<stdio.h>
struct student {
int num;
char name[20];
int grade1, grade2, grade3;
}stus[5];
void input(student a[]) {
for (int i = 0;i < 5;++i) {
scanf("%d %s %d %d %d", &stus[i].num, stus[i].name, &stus[i].grade1, &stus[i].grade2, &stus[i].grade3);
}
}
void print(student a[]) {
for (int i = 0;i < 5;++i) {
printf("%d %s %d %d %d\n", stus[i].num, stus[i].name, stus[i].grade1, stus[i].grade2, stus[i].grade3);
}
}
int main() {
input(stus);
print(stus);
return 0;
}
C语言11.8
#include<cstdio>
struct student {
int num;
char name[20];
int g1, g2, g3;
}stus[10];
int main() {
for (int i = 0;i < 10;++i) {
scanf("%d %s %d %d %d", &stus[i].num, stus[i].name, &stus[i].g1, &stus[i].g2, &stus[i].g3);
}
double ave1=0, ave2=0, ave3=0;
int max = -1,n;
for (int i = 0;i < 10;++i) {
ave1 += 1.0*stus[i].g1;
ave2 += 1.0*stus[i].g2;
ave3 += 1.0*stus[i].g3;
if ((stus[i].g1 + stus[i].g2 + stus[i].g3) > max) {
max = stus[i].g1 + stus[i].g2 + stus[i].g3;
n = i;
}
}
ave1 /= 10.0;
ave2 /= 10.0;
ave3 /= 10.0;
printf("%.2f %.2f %.2f \n", ave1, ave2, ave3);
printf("%d %s %d %d %d\n", stus[n].num, stus[n].name, stus[n].g1, stus[n].g2, stus[n].g3);
return 0;
}
《算法笔记》2.9小节——C/C++快速入门->补充
重点:
- 浮点数经过大量计算后存储的精准性可能会下降因此使用如下几种宏定义来对浮点数进行比较;
#include<cmath>
const double eps = 1e-8;//对大多数情况不会漏判也不会误判
#define Equ(a,b) ((fabs((a)-(b)))<(eps))
#define More(a,b) ((fabs((a)-(b)))>(eps))
#define Less(a,b) ((fabs((a)-(b)))>(-eps))
#define MoreEqu(a,b) (((a)-(b))>(-eps))
#define LessEqu(a,b) (((a)-(b))<(eps))
- 圆周率π
const double Pi = acos(-1.0);//acos在#include<cmath>中
《算法笔记》2.10小节——C/C++快速入门->黑盒测试
多点测试中有如下结构用于反复执行程序的核心部分:
三种输入类型:
while-EOF
类型 :如while (scanf("%d", &a) != EOF)
;while (scanf("%s", s) != EOF)
;while (gets(str) != NULL)
等用于输入字符串和数值。如练习I。while-EOF-break
类型:输入数据满足某个条件时退出,如while (scanf("%d %d", &a, &b) != EOF, a | b)
。如练习III。while (T--)
类型,给出测试数据的组数。如练习II。
三种输出类型:
- 正常输出:输出数据是连续的多行。
- 每组数据输出之后都额外加一个空行:只需要在每组输出结束后额外输出一个换行符\n即可。如练习VII。
- 两组数据之间有一个空行,最后一组数据后面没有空行:只需要通过判断T是否已经减小到0来判断是否应当输出额外的换行。如练习VIII。同理的还有N个整数,每两个整数之间用空格隔开,每行最后一个整数后不允许加上空格。
A+B 输入输出练习I
#include<cstdio>
int main() {
int a, b;
while (scanf("%d %d", &a, &b) != EOF) printf("%d\n", a + b);
return 0;
}
A+B 输入输出练习II
#include<cstdio>
int main() {
int a, b, T;
scanf("%d", &T);
while (T--) {
scanf("%d %d", &a, &b);
printf("%d\n", a + b);
}
return 0;
}
A+B 输入输出练习III
#include<cstdio>
int main() {
int a, b;
while (scanf("%d %d", &a, &b) != EOF, a || b) {
printf("%d\n", a + b);
}
return 0;
}
A+B 输入输出练习IV
#include<cstdio>
int main() {
int n, sum = 0;
while (scanf("%d", &n) != EOF, n) {
while (n--) {
int temp;
scanf("%d", &temp);
sum += temp;
}
printf("%d\n", sum);
sum = 0;
}
return 0;
}
A+B 输入输出练习V
#include<cstdio>
int main() {
int n, sum = 0;
scanf("%d", &n);
while (n--) {
int m;
scanf("%d", &m);
while (m--) {
int temp;
scanf("%d", &temp);
sum += temp;
}
printf("%d\n", sum);
sum = 0;
}
return 0;
}
A+B 输入输出练习VI
#include<cstdio>
int main() {
int n, sum = 0;
while (scanf("%d", &n) != EOF) {
while (n--) {
int temp;
scanf("%d", &temp);
sum += temp;
}
printf("%d\n", sum);
sum = 0;
}
return 0;
}
A+B 输入输出练习VII
#include<cstdio>
int main() {
int a, b;
while (scanf("%d %d", &a, &b) != EOF) {
printf("%d\n\n", a + b);
}
}
A+B 输入输出练习VIII
#include<cstdio>
int main() {
int n, T, sum;
scanf("%d", &T);
while (T--) {
int n;
scanf("%d", &n);
while (n--) {
int temp;
scanf("%d", &temp);
sum += temp;
}
printf("%d\n\n", sum);
sum = 0;
}
return 0;
}
《算法笔记》3.1小节——入门模拟->简单模拟
Codeup
剩下的树
#include<cstdio>
#include<cstring>
int main() {
int l, m;
int point[10001];
while ((scanf("%d %d", &l, &m)) != EOF) {
if (l == 0 && m == 0) break;
memset(point, -1, (l + 1) * sizeof(int));
for (int i = 0;i < m;++i) {
int dl, dr;
scanf("%d %d", &dl, &dr);
dr = dr - dl + 1;
for (int j = 0;j < dr;++j) {
if (point[dl] != 0) point[dl] = 0;
++dl;
}
}
int cnt = 0;
for (int i = 0;i <= l;++i) {
if (point[i] == -1) ++cnt;
}
printf("%d\n", cnt);
}
return 0;
}
A+B
输入输出都是对的但是判定我错,找了好久错误心好累。
#include<cstdio>
int main() {
char number[11];
char c;
long long a, b;
int temp = 0, t = 0;
while (scanf("%c", &c) != EOF) {
if (c >= '0' && c <= '9' || c == '-') {
number[temp++] = c;
}
else if (c == ',');
else {
number[temp] = '\0';
if (++t % 2) sscanf(number, "%lld", &a);
else {
sscanf(number, "%lld", &b);
printf("%lld\n", a + b);
}
temp = 0;
}
}
return 0;
}
正确代码
#include <cstdio>
#include <cstring>
long long to_int(char s[]) {
int len = strlen(s);
long long r = 0;
int positive = 1;
for (int i = 0; i < len; i++) {
if (s[i] <= '9' && s[i] >= '0') {
r = r * 10 + (s[i] - '0');
} else if (s[i] == '-')
positive = 0;
}
if (!positive) r = -r;
return r;
}
int main()
{
char s[50], r[50];
while (scanf("%s %s", s, r) != EOF) {
long long snum, rnum;
snum = to_int(s);
rnum = to_int(r);
printf("%lld\n", snum + rnum);
}
return 0;
}
特殊乘法
#include<cstdio>
int main() {
long long a, b;
int ap[11] = { 0 }, bp[11] = { 0 }, na, nb, i;
while (scanf("%lld %lld", &a, &b) != EOF) {
for (i = 0;a != 0;++i) {
ap[i] = a % 10;//不用在意存取的顺序是否为从大到小
a /= 10;
}
na = i;
for (i = 0;b != 0;++i) {
bp[i] = b % 10;
b /= 10;
}
nb = i;
int sum = 0;
for (i = 0;i < na;++i) {
for (int j = 0;j < nb;++j) {
sum += (ap[i] * bp[j]);
}
}
printf("%d\n", sum);
}
}
比较奇偶数个数
#include<cstdio>
int main() {
int n;
while (scanf("%d", &n) != EOF) {
int odd = 0, even = 0;
for (int i = 0;i < n;++i) {
int temp;
scanf("%d", &temp);
if (temp % 2) ++odd;
else ++even;
}
if (odd >= even) printf("YES\n");
else printf("NO\n");
}
}
Shortest Distance (20)
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 100005;
int main() {
int n,m;
int round=0,distance[MAXN] = { 0 }, a[MAXN] = { 0 };
scanf("%d", &n);
for (int i = 1;i <= n;++i) {
scanf("%d", &a[i]);
round += a[i];
distance[i] = round;
}
scanf("%d", &m);
int left, right;
for (int i = 0;i < m;++i) {
scanf("%d %d", &left, &right);
if (left > right) swap(left, right);
int temp = distance[right - 1] - distance[left - 1];
printf("%d", min(temp, round - temp));
if (i + 1 != m) printf("\n");
}
}
A+B和C (15)
#include<cstdio>
int main() {
long long a, b, c;
int n;
scanf("%d", &n);
for (int i = 1;i <= n;++i) {
scanf("%lld %lld %lld", &a, &b, &c);
if (a + b > c) printf("Case #%d: true", i);
else printf("Case #%d: false", i);
if (i != n) printf("\n");
}
return 0;
}
数字分类(20)
#include<cstdio>
const int NUM = 5;
int main() {
int n, flag = 1;
int cnt[NUM] = { 0 }, res[NUM] = { 0 };
scanf("%d", &n);
while (n--) {
int temp;
scanf("%d", &temp);
if (!(temp % 5)) {
if (!(temp % 2)) {
++cnt[0];
res[0] += temp;
}
}
else if (temp % 5 == 1) {
++cnt[1];
res[1] += temp * flag;
flag *= -1;
}
else if (temp % 5 == 2) {
++cnt[2];
}
else if (temp % 5 == 3) {
++cnt[3];
res[3] += temp;
}
else {
++cnt[4];
if (temp > res[4]) res[4] = temp;
}
}
if (cnt[0] == 0) printf("N ");
else printf("%d ", res[0]);
if (cnt[1] == 0) printf("N ");
else printf("%d ", res[1]);
if (cnt[2] == 0) printf("N ");
else printf("%d ", cnt[2]);
if (cnt[3] == 0) printf("N ");
else printf("%.1f ", 1.0 * res[3] / cnt[3]);
if (cnt[4] == 0) printf("N");
else printf("%d", res[4]);
return 0;
}
锤子剪刀布(20)
#include<cstdio>
int change(char c) {
int res;
if (c == 'B') res = 0;
else if (c == 'C') res = 1;
else if (c == 'J') res = 2;
return res;
}
int main() {
int n;
char cha[3] = {'B','C','J'};
int awin = 0, alose = 0, ab = 0;
int hand_a[3] = { 0 }, hand_b[3] = { 0 };
scanf("%d", &n);
while (n--) {
getchar();
char c1, c2;
int k1, k2;
scanf("%c %c", &c1, &c2);
k1 = change(c1);
k2 = change(c2);
if ((k1 + 1) % 3 == k2) {
++awin;
++hand_a[k1];
}
else if ((k2 + 1) % 3 == k1) {
++alose;
++hand_b[k2];
}
else ++ab;
}
printf("%d %d %d\n", awin, ab, alose);
printf("%d %d %d\n", alose, ab, awin);
int ma=0, mb=0;
for (int i = 0;i < 3;++i) {
if (hand_a[i] > hand_a[ma]) ma = i;
if (hand_b[i] > hand_b[mb]) mb = i;
}
printf("%c %c", cha[ma], cha[mb]);
return 0;
}
配套实战指南
PAT B1001 害死人不偿命的(3n+1)猜想
#include<cstdio>
int main() {
int num, times = 0;
scanf("%d", &num);
while (num - 1) {
if (num % 2 == 0) num /= 2;
else num = (3 * num + 1) / 2;
++times;
}
printf("%d", times);
return 0;
}
PAT B1011 A+B 和 C
#include<cstdio>
int main() {
int n;
scanf("%d", &n);
for (int i = 0;i < n;++i) {
long long a, b, c;
scanf("%lld %lld %lld", &a, &b, &c);
if (a + b > c) printf("Case #%d: true\n", i + 1);
else printf("Case #%d: false\n", i + 1);//PAT平台的结尾无空行整的我无语了
}
return 0;
}
PAT B1016 部分A+B
#include<cstdio>
int main() {
int a, b, da, db, pa=0, pb=0;
scanf("%d %d %d %d", &a, &da, &b, &db);
for (;a > 0;a /= 10) {
if (a % 10 == da) pa = 10 * pa + da;
}
for (;b > 0;b /= 10) {
if (b % 10 == db) pb = 10 * pb + db;
}
printf("%d", pa + pb);
return 0;
}
PAT B1026 程序运行时间
#include<cstdio>
#include<cmath>
const int CLKTCK = 100;
int main() {
int c1, c2;
int c;
scanf("%d %d", &c1, &c2);
c = (int)round(1.0 * (c2 - c1) / CLKTCK);
int h, m, s;
s = c % 60;
c /= 60;
m = c % 60;
h = c / 60;
printf("%02d:%02d:%02d", h, m, s);
return 0;
}
PAT B1046 划拳
#include<cstdio>
int main() {
int T;
int d1 = 0, d2 = 0;
scanf("%d", &T);
while (T--) {
int a, b, c, d;
scanf("%d %d %d %d", &a, &b, &c, &d);
if (a + c == b && a + c == d) continue;
else if (a + c == b) ++d2;
else if (a + c == d) ++d1;
else continue;
}
printf("%d %d", d1, d2);
return 0;
}
PAT B1008 数组元素循环右移问题
#include<cstdio>
void invert(int a[], int start, int m) {
while (m > start) {
int temp = a[start];
a[start] = a[m];
a[m] = temp;
++start;
--m;
}
}
int main() {
int n, m, a[101] = { 0 };
scanf("%d %d", &n, &m);
m %= n;
for (int i = 0;i < n;++i) {
scanf("%d", a + i);
}
if (m > 0 && n > 1) {
invert(a, 0, n - m - 1);//这里用的是反复调转
invert(a, n - m, n - 1);
invert(a, 0, n - 1);
}
for (int i = 0;i < n;++i) {
if (i) printf(" ");
printf("%d", a[i]);
}
return 0;
}
PAT B1012数字分类
这题排查bug花了很长时间
A1处出错,因为%5没有余数且为奇数的数字会进最后那个else分支,这显然不对,最后一个else分支其实是对应%5==4的,
#include<cstdio>
int main() {
int n;
int ans[5] = { 0 }, cnt[5] = { 0 }, flag = 1;
scanf("%d", &n);
for (int i = 0;i < n;++i) {
int temp;
scanf("%d", &temp);
if (!(temp % 5)){//不可写成逻辑与判断
if (!(temp % 2)) {
++cnt[0];
ans[0] += temp;
}
}
else if (temp % 5 == 1) {
++cnt[1];
ans[1] += flag * temp;
flag *= -1;
}
else if (temp % 5 == 2) {
++cnt[2];
++ans[2];
}
else if (temp % 5 == 3) {
++cnt[3];
ans[3] += temp;
}
else {
++cnt[4];
if (ans[4] < temp) ans[4] = temp;
}
}
if (!cnt[0]) printf("N");
else printf("%d", ans[0]);
if (!cnt[1]) printf(" N");
else printf(" %d", ans[1]);
if (!cnt[2]) printf(" N");
else printf(" %d", ans[2]);
if (!cnt[3]) printf(" N");
else printf(" %.1f", 1.0 * ans[3] / cnt[3]);
if (!cnt[4]) printf(" N");
else printf(" %d", ans[4]);
return 0;
}
PAT B1018 锤子剪刀布
写了好长都快把自己搞晕了
重点是getchar();
吸收每次输入后的’\n’
这种题不能硬莽,像书上将BCJ转化成——012,并以+1后是否相等判断输赢会更好。
#include<cstdio>
//B 代表“布” 、C 代表“锤子”、J 代表“剪刀”、,
int main() {
int n;
int awin = 0, ab = 0, alose = 0;
int acnt[3] = { 0 }, bcnt[3] = { 0 };
scanf("%d", &n);
while (n--) {
getchar();
char a, b;
scanf("%c %c", &a, &b);
if (a == 'C') {
if (b == 'C') ++ab;
else if (b == 'J') {
++awin;
++acnt[1];
}
else if (b == 'B') {
++alose;
++bcnt[0];
}
}
else if (a == 'J') {
if (b == 'C') {
++alose;
++bcnt[1];
}
else if (b == 'J') ++ab;
else if (b == 'B') {
++awin;
++acnt[2];
}
}
else {
if (b == 'C') {
++awin;
++acnt[0];
}
else if (b == 'J') {
++alose;
++bcnt[2];
}
else if (b == 'B') ++ab;
}
}
printf("%d %d %d\n", awin, ab, alose);
printf("%d %d %d\n", alose, ab, awin);
int maxa = 0, maxb = 0, a = 0, b = 0;
for (int i = 0;i < 3;++i) {
if (acnt[i] > maxa) {
maxa = acnt[i];
a = i;
}
if (bcnt[i] > maxb) {
maxb = bcnt[i];
b = i;
}
}
switch (a) {
case 0:
printf("B ");
break;
case 1:
printf("C ");
break;
case 2:
printf("J ");
break;
}
switch (b) {
case 0:
printf("B");
break;
case 1:
printf("C");
break;
case 2:
printf("J");
break;
}
return 0;
}
PAT A1042 Shuffling Machine
加油努力吧,就差一点就全对了。
#include<cstdio>
const int N = 54;
char mp[5] = { 'S','H','C','D','J' };
int main() {
int start[N+1], end[N+1], next[N+1];
int n;
scanf("%d", &n);
for (int i = 1;i <= N ;++i) {
start[i] = i;
}
for (int i = 1;i <= N;++i) {
scanf("%d", &next[i]);
}
for (int step = 0;step < n;++step) {
for (int i = 1;i <= N;++i) {
end[next[i]] = start[i];
}
for (int i = 1;i <= N;++i) {
start[i] = end[i];
}
}
for (int i = 1;i <= 54;++i) {
if (i != 1) printf(" ");
printf("%c%d", mp[(start[i] - 1) / 13], (start[i] - 1) % 13 + 1);
}
return 0;
}
PAT A1046 Shortest Distance
本题满分的关键在于使用D[]数组表示1号结点按顺时针方向到达“i号结点顺时针方向的下一个结点”的距离,最后只需比较round-dis(left,right)和dis(left,right);
另外对algorithm库函数的初步了解;
#include<cstdio>
#include<algorithm>
using namespace std;
int main() {
int m,n,round=0;
int D[100001] = { 0 }, A[100001] = { 0 };
scanf("%d", &n);
for (int i=1;i <= n;++i) {
int d;
scanf("%d", &d);
A[i] = d;
round += d;
D[i] = round;
}
scanf("%d", &m);
for (int i = 0;i < m;++i) {
int left,right;
scanf("%d %d", &left, &right);
if (left > right) swap(left, right);//left > right时交换
int temp = D[right - 1] - D[left - 1];
printf("%d", min(temp,round-temp));
if (i + 1 != m) printf("\n");
}
}
PAT A1065 A+B and C(64bit)
本题做全对的关键在于溢出判断
正数相加和为负数,
负数相加和为正数
同时要注意两边界的判定(本题中负数溢出res可得0)
#include<cstdio>
int main() {
long long a, b, c;
int n;
scanf("%d", &n);
for (int i = 0;i < n;++i) {
scanf("%lld %lld %lld", &a, &b, &c);
long long res = a + b;
if (res < 0 && a>0 && b > 0) printf("Case #%d: true\n", i + 1);
else if (res >= 0 && a < 0 && b < 0) printf("Case #%d: false\n", i + 1);
else if (a + b > c) printf("Case #%d: true\n", i + 1);
else printf("Case #%d: false\n", i + 1);
}
}
PAT B1010 一元多项式求导
求导部分必须从低次项枚举到高次项,否则结果出错,另外求导之后没有非零项则应输出0 0。
#include<cstdio>
int main() {
int a[1010] = {0};
int n = 0;
while (scanf("%d", &a[n++]) != EOF);
for (int i = 0;i < n;++i) {
if (i % 2 == 0) {
a[i] *= a[i + 1];
}
else {
if (a[i] == 0) break;
else {
--a[i];
}
}
}
for (int i = 0;i < n;++i) {
if (i == 0 && a[i] == 0) {
printf("0 0");
break;
}
else if (i % 2 == 0 && a[i] == 0) break;
else {
if (i != 0) printf(" ");
printf("%d", a[i]);
}
}
}
1002 A+B for Polynomials
#include<cstdio>
int main() {
int n;
int e;
double k;
double a[1010] = { 0 };
scanf("%d", &n);
for (int i = 0;i < n;++i) {
scanf("%d %lf", &e, &k);
a[e] = k;
}
scanf("%d", &n);
for (int i = 0;i < n;++i) {
scanf("%d %lf", &e, &k);
a[e] += k;
}
int cnt = 0;
for (int i = 0;i < 1010;++i) if (a[i] != 0) cnt++;
printf("%d", cnt);
for (int i = 1009;i >= 0;--i) {
if (a[i]!=0) printf(" %d %.1f", i, a[i]);
}
}
PAT A1009 Product of Polynomials
#include<cstdio>
int main() {
int n;
int e;
double k;
double a[1001] = { 0 }, b[2001] = { 0 };
scanf("%d", &n);
for (int i = 0;i < n;++i) {
scanf("%d %lf", &e, &k);
a[e] = k;
}
scanf("%d", &n);
for (int i = 0;i < n;++i) {
scanf("%d %lf", &e, &k);
for (int j = 0;j < 1001;++j) {
if (a[j] != 0) {
int t = j + e;
b[t] += a[j] * k;
}
}
}
int cnt = 0;
for (int i = 0;i < 2001;++i) if (b[i] != 0) cnt++;
printf("%d", cnt);
for (int i = 2000;i >= 0;--i) {
if (b[i]) printf(" %d %.1f", i, b[i]);
}
}
《算法笔记》3.2小节——入门模拟->查找元素
Codeup
统计同成绩学生人数
#include<cstdio>
int main() {
int n;
int grade[1001];
while (scanf("%d", &n) != EOF && n != 0) {
for (int i = 0;i < n;++i) {
scanf("%d", grade + i);
}
int cmp, cnt = 0;
scanf("%d", &cmp);
for (int i = 0;i < n;++i) {
if (cmp == grade[i]) ++cnt;
}
printf("%d\n", cnt);
}
return 0;
}
找x
#include<cstdio>
int main() {
int n;
int num[200];
while (scanf("%d", &n) != EOF) {
for (int i = 0;i < n;++i) {
scanf("%d", num + i);
}
int search,i;
scanf("%d", &search);
for (i = 0;i < n;++i) {
if (search = num[i]) {
printf("%d\n", i);
break;
}
}
if (i == n) printf("-1\n");
}
return 0;
}
查找学生信息
本题正确的关键在于CodeUp是多点测试,另外char name[]
要多申请一些空间,不然会出错
#include<cstdio>
#include<cstring>
struct student {
char id[10];
char name[100];
char gender[10];
int age;
}stus[1000];
int main() {
int n;
while (scanf("%d", &n) != EOF) {
for (int i = 0;i < n;++i) {
scanf("%s %s %s %d", stus[i].id, stus[i].name, stus[i].gender, &stus[i].age);
}
int m;
scanf("%d", &m);
for (int i = 0;i < m;++i) {
char temp[10];
scanf("%s", temp);
int j;
for (j = 0;j < n;++j) {
if (strcmp(temp, stus[j].id) == 0) {
printf("%s %s %s %d\n", stus[j].id, stus[j].name, stus[j].gender, stus[j].age);
break;
}
}
if (j == n) printf("No Answer!\n");
}
}
return 0;
}
查找
#include<cstdio>
int main() {
int n, m;
int a[100], b[100];
while (scanf("%d", &n) != EOF) {
for (int i = 0;i < n;++i) scanf("%d", a + i);
scanf("%d", &m);
for (int i = 0;i < m;++i) {
scanf("%d", b + i);
int j;
for (j = 0;j < n;++j) {
if (a[j] == b[i]) {
printf("YES\n");
break;
}
}
if (j == n) printf("NO\n");
}
}
return 0;
}
学生查询
#include<cstdio>
struct student {
int id;
char name[100];
char gender[10];
int age;
}stus[100];
int main() {
int n;
scanf("%d", &n);
while (n--) {
int m;
scanf("%d", &m);
for (int i = 0;i < m;++i) scanf("%d %s %s %d", &stus[i].id, stus[i].name, stus[i].gender, &stus[i].age);
int searching;
scanf("%d", &searching);
for (int i = 0;i < m;++i)
if (searching == stus[i].id)
printf("%d %s %s %d\n", stus[i].id, stus[i].name, stus[i].gender, stus[i].age);
}
return 0;
}
配套实战指南
PTA B1041 考试座位号
#include<cstdio>
struct Student {
long long id;
int t, e;
}stu[1000];
int main() {
int n, m;
scanf("%d", &n);
for (int i = 0;i < n;++i) {
scanf("%lld %d %d", &stu[i].id, &stu[i].t, &stu[i].e);
}
scanf("%d", &m);
while (m--) {
int temp;
scanf("%d", &temp);
for (int i = 0;i < n;++i) {
if (stu[i].t == temp) {
printf("%lld %d\n", stu[i].id, stu[i].e);
break;
}
}
}
return 0;
}
PTA 1004 成绩排名
#include<cstdio>
struct Student {
char name[11], id[11];
int grade;
}stu[101];
int main() {
int n;
int max = -1, min = 101, maxn = 0, minn = 0;
scanf("%d", &n);
for (int i = 0;i < n;++i) {
scanf("%s %s %d", &stu[i].name, &stu[i].id, &stu[i].grade);
if (stu[i].grade > max) {
max = stu[i].grade;
maxn = i;
}
if (stu[i].grade < min) {
min = stu[i].grade;
minn = i;
}
}
printf("%s %s\n", stu[maxn].name, stu[maxn].id);
printf("%s %s", stu[minn].name, stu[minn].id);
return 0;
}
PTA 1028 人口普查
本题要注意的点有
①有可能所有人的日期都为不合法,这时应if (cnt == 0) printf("0");
否则回因后面多输入空格而返回“格式错误”。
②日期比较函数不能只写一个单独的bool compare(persons i,persons j);
,应分开写成bool LessEqu(persons i, persons j)
和bool MoreEqu(persons i, persons j)
。
③应当注意tooold和haventburn谁为左边界谁为有边界,或可直接改成left和right。
#include<cstdio>
struct persons {
char name[6];
int year, month, day;
}old, young, temp, tooold, haventburn;
bool LessEqu(persons i, persons j) {
if (i.year != j.year) return i.year <= j.year;
else if (i.month != j.month) return i.month <= j.month;
else return i.day <= j.day;
}
bool MoreEqu(persons i, persons j) {
if (i.year != j.year) return i.year >= j.year;
else if (i.month != j.month) return i.month >= j.month;
else return i.day >= j.day;
}
bool qualify(persons i) {
if (MoreEqu(i, tooold) && LessEqu(i, haventburn)) return 1;
else return 0;
}
void init() {
young.year = tooold.year = 1814;
old.year = haventburn.year = 2014;
young.month = old.month = haventburn.month = tooold.month = 9;
young.day = old.day = haventburn.day = tooold.day = 6;
}
int main() {
int n, cnt = 0;
init();
scanf("%d", &n);
while (n--) {
scanf("%s %d/%d/%d", &temp.name, &temp.year, &temp.month, &temp.day);
if (qualify(temp)) {
++cnt;
if (MoreEqu(temp, young)) young = temp;
if (LessEqu(temp, old)) old = temp;
}
}
if (cnt == 0) printf("0");
else printf("%d %s %s", cnt, old.name, young.name);
return 0;
}
PAT B 1032 挖掘机技术哪家强
#include<cstdio>
const int maxn = 100010;
int main() {
int n;
int score[maxn] = { 0 };
scanf("%d", &n);
for (int i = 0;i < n;++i) {
int j, s;
scanf("%d %d", &j, &s);
score[j] += s;
}
int maxschool = 1, max = -1;
for (int i = 1;i <= n;++i) {
if (score[i] > max) {
max = score[i];
maxschool = i;
}
}
printf("%d %d\n", maxschool, max);
return 0;
}
PTA A1011 World Cup Betting
#include<cstdio>
int main() {
double W, T, L;
double res[3];
for (int i = 0;i < 3;++i) {
scanf("%lf %lf %lf", &W, &T, &L);
double max;
if (W > T && W > L) {
printf("W ");
res[i] = W;
}
else if (T > W && T > L) {
printf("T ");
res[i] = T;
}
else {
printf("L ");
res[i] = L;
}
}
printf("%.2f", (res[0] * res[1] * res[2] * 0.65 - 1) * 2);
return 0;
}
PTA A1006 Sign In and Sign Out
本题如果使用hh/mm/ss即代表sign_in时间又代表sin_out时间,可以减少很多代码量。
#include<cstdio>
struct student {
char ID_number[16];
int inhh, inmm, inss;
int outhh, outmm, outss;
}temp, earliest, latest;
bool sign_in_earlier(student i, student j) {
if (i.inhh != j.inhh) return i.inhh < j.inhh;
else if (i.inmm != j.inmm) return i.inmm < j.inmm;
else return i.inss < j.inss;
}
bool sign_out_later(student i, student j) {
if (i.outhh != j.outhh) return i.outhh > j.outhh;
else if (i.outmm != j.outmm) return i.outmm > j.outmm;
else return i.outss > j.outss;
}
int main() {
int n;
earliest.inhh = 25;
latest.outhh = -1;
scanf("%d", &n);
for (int i = 0;i < n;++i) {
getchar();
scanf("%s %d:%d:%d %d:%d:%d", temp.ID_number, &temp.inhh, &temp.inmm, &temp.inss, &temp.outhh, &temp.outmm, &temp.outss);
if (sign_in_earlier(temp, earliest)) earliest = temp;
if (sign_out_later(temp, latest)) latest = temp;
}
printf("%s %s", earliest.ID_number, latest.ID_number);
return 0;
}
PTA A1036 Boys vs Girls
#include<cstdio>
struct student {
char name[11],ID[11];
char gender;
int grade;
}lgm,hgf,temp;
int main() {
int n, nf = 0, nm = 0;
lgm.grade = 100;
hgf.grade = 0;
scanf("%d", &n);
for (int i = 0;i < n;++i) {
scanf("%s %c %s %d", temp.name, &temp.gender, temp.ID, &temp.grade);
if (temp.gender == 'F' && temp.grade > hgf.grade) {
hgf = temp;
++nf;
}
else if (temp.gender == 'M' && temp.grade < lgm.grade) {
lgm = temp;
++nm;
}
}
if (nf == 0) printf("Absent\n");
else printf("%s %s\n", hgf.name, hgf.ID);
if (nm == 0) printf("Absent\n");
else printf("%s %s\n", lgm.name, lgm.ID);
if (nm == 0 || nf == 0) printf("NA");
else printf("%d", hgf.grade - lgm.grade);
return 0;
}
《算法笔记》3.3小节——入门模拟->图形输出
Codeup
输出梯形
#include<cstdio>
int main() {
int h;
while (scanf("%d", &h) != EOF) {
int n = (h - 1) * 2 + h;
int m = h;
for (int i = 0;i < m;++i) {
for (int j = 0;j < n - h;++j) printf(" ");
for (int j = 0;j < h;++j) printf("*");
printf("\n");
h += 2;
}
}
return 0;
}
Hello World for U
这里采用的是公式法+二维数组法
#include<cstdio>
#include<cstring>
int main() {
char str[100], ans[40][40];
scanf("%s", str);
int N = strlen(str);
int n1 = (N + 2) / 3, n3 = n1, n2 = N + 2 - n1 - n3;
memset(ans, ' ', sizeof(ans));
int pos = 0;
for (int i = 1;i <= n1;++i) ans[i][1] = str[pos++];
for (int i = 2;i < n2;++i) ans[n1][i] = str[pos++];
for (int i = n3;i >= 1;--i) ans[i][n2] = str[pos++];
for (int i = 1;i <= n1;++i) {
for (int j = 1;j <= n2;++j) {
printf("%c", ans[i][j]);
}
if(i!=n1) printf("\n");
}
return 0;
}
等腰梯形
#include<cstdio>
int main() {
int t,h;
scanf("%d", &t);
while (t--) {
scanf("%d", &h);
int n = 3 * h - 2, m = h;
int spacenum = (n - h) / 2;
for (int i = 0;i < h;++i) {
for (int j = 0;j < spacenum;++j) printf(" ");
for (int j = 0;j < m;++j) printf("*");
--spacenum;
m += 2;
printf("\n");
}
}
return 0;
}
沙漏图形 tri2str [1*+]
#include<cstdio>
int main() {
int n;
while (scanf("%d", &n) != EOF) {
int m = n;
for (int i = 0;i < n;++i) {
for (int j = 0;j < i;++j) printf(" ");
for (int j = 0;j < m;++j) printf("* ");
printf("\n");
--m;
}
m = n;
for (int i = n - 1;i > 0;--i) {
for (int j = 0;j < i - 1;++j) printf(" ");
for (int j = 0;j < n - m + 2;++j) printf("* ");
printf("\n");
--m;
}
}
return 0;
}
配套实战指南
PTA B1036 跟奥巴马一起编程
#include<cstdio>
#include<cmath>
int main() {
int n, m;
char c;
scanf("%d %c", &n, &c);
m = (int)round(n / 2.0);
for (int i = 0;i < m;++i) {
if (i == 0 || i == m - 1) {
for (int j = 0;j < n;++j) {
printf("%c", c);
if (j == n - 1) printf("\n");
}
}
else {
printf("%c", c);
for (int i = 0;i < n - 2;++i) printf(" ");
printf("%c\n", c);
}
}
return 0;
}
PAT B1027 打印沙漏
最开始在输出的每行*后面也加入了空格导致有判定点没过
#include<cstdio>
int main() {
int n, res = 1;
int m = 3, rem;
char c;
scanf("%d %c", &n, &c);
while ((res + 2 * m) < n) {
res += 2 * m;
m += 2;
}
m -= 2;
rem = n - res;
for (int i = 0;i <= m / 2;++i) {
for (int j = 0;j < i;++j) printf(" ");
for (int j = 0;j < m - 2 * i;++j) printf("%c", c);
printf("\n");
}
for (int i = m / 2 - 1;i >= 0;--i) {
for (int j = 0;j < i;++j) printf(" ");
for (int j = 0;j < m - 2 * i;++j) printf("%c", c);
printf("\n");
}
printf("%d", rem);
return 0;
}
PAT A1031 Hello World for U
本题的关键在于理解n1 =n3 =max { k | k≤n2 for all 3≤n2≤N } with n1 +n2 +n3−2=N
条件,即为n1+n2+n3-2=N n1=n3=k<=n2
,意思即为n1,n3在不大于n2的情况下尽可能大。可像实战指南书中所提找到规律为n1、n3总是取(N+2)/3
,如若未发现规律亦可采用枚举法取出n1、n2、n3的取值。
输出可采用二维数组的方式或者直接输出。
在此,我使用枚举法+直接输出
#include<cstdio>
#include<cstring>
int main() {
int n1 = 1, n2 = 0, cnt;
char str[85];
scanf("%s", str);
cnt = n2 = strlen(str);
while (n1 + 1 <= n2 - 2) {
n2 -= 2;
++n1;
}
for (int i = 0;i < n1-1;++i) {
printf("%c", str[i]);
for (int j = 0;j < n2 - 2;++j) printf(" ");
printf("%c\n", str[cnt - i - 1]);
}
for (int i = n1-1;i < n2 + n1-1;++i) {
printf("%c", str[i]);
}
return 0;
}
《算法笔记》3.4小节——入门模拟->日期处理
日期差值
#include<cstdio>
#include<algorithm>
using namespace std;
int month[13][2] = { {0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},
{31,31},{30,30},{31,31},{30,30},{31,31 } };
bool isleap(int year) {
return (year % 400 == 0 || (year % 4 == 0) && (year % 100 != 0));
}
int main() {
int time1, y1, m1, d1, time2, y2, m2, d2;
while (scanf("%d%d", &time1, &time2) != EOF) {
if (time1 > time2) swap(time1, time2);
y1 = time1 / 10000, m1 = time1 % 10000 / 100, d1 = time1 % 100;
y2 = time2 / 10000, m2 = time2 % 10000 / 100, d2 = time2 % 100;
int ans = 1;
while (y1 < y2 || m1 < m2 || d1 < d2) {
++d1;
if (d1 > month[m1][isleap(y1)]) {
d1 = 1;
++m1;
}
if (m1 > 12) {
m1 = 1;
++y1;
}
++ans;
}
printf("%d\n", ans);
}
return 0;
}
Day of Week
写了老长时间,总的来说就是数天数+算周几的事,但是需要注意的细节很多,以及还有英文与数字的转换,写好之后发现不正确找了很久问题,问题在最后的结果计算上,相隔7天的周五会出现输出空白的情况。
#include<cstdio>
#include<cstring>
using namespace std;
const int ty = 2021, tm = 8, td = 6, twd = 5;
int month[13][2] = { {0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},
{31,31},{30,30},{31,31},{30,30},{31,31 } };
bool isleap(int year) {
return (year % 400 == 0 || (year % 4 == 0) && (year % 100 != 0));
}
char eweekday[8][15] = { {'\0'},{"Monday"},{"Tuesday"},{"Wednesday"},{"Thursday"},{"Friday"},
{"Saturday"},{"Sunday"} };
int Tomonth(char str[]) {
if (strcmp(str, "January") == 0) return 1;
else if (strcmp(str, "February") == 0) return 2;
else if (strcmp(str, "March") == 0) return 3;
else if (strcmp(str, "April") == 0) return 4;
else if (strcmp(str, "May") == 0) return 5;
else if (strcmp(str, "June") == 0) return 6;
else if (strcmp(str, "July") == 0) return 7;
else if (strcmp(str, "August") == 0) return 8;
else if (strcmp(str, "September") == 0) return 9;
else if (strcmp(str, "October") == 0) return 10;
else if (strcmp(str, "November") == 0) return 11;
else return 12;
}
bool isMore(int y, int m, int d) {
if (y != ty) return y > ty;
else if (m != tm) return m > tm;
else return d > td;
}
int main() {
int d, y, m, ans;
char em[15];
while (scanf("%d %s %d", &d, em, &y) != EOF) {
m = Tomonth(em);
int sy, sm, sd, ly, lm, ld;
if (isMore(y, m, d)) {
ly = y;
lm = m;
ld = d;
sy = ty;
sm = tm;
sd = td;
}
else {
ly = ty;
lm = tm;
ld = td;
sy = y;
sm = m;
sd = d;
}
ans = 0;
while (sd < ld || sm < lm || sy < ly) {
++sd;
if (sd > month[sm][isleap(sy)]) {
++sm;
sd = 1;
}
if (sm > 12) {
++sy;
sm = 1;
}
++ans;
}
int res = ans % 7;
if (isMore(y, m, d)) {
if (twd + res > 7) res = twd + res - 7;
else res = twd + res;
}
else {
if (twd - res <= 0) res = twd - res + 7;
else res = twd - res;
}
printf("%s\n", eweekday[res]);
}
return 0;
}
打印日期
本题相对简单,答案正确错了几次之后发现竟然是年份那里要写成%04d
#include<cstdio>
int month[13][2] = { {0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},
{31,31},{30,30},{31,31},{30,30},{31,31 } };
bool isleap(int year) {
return (year % 400 == 0 || (year % 4 == 0) && (year % 100 != 0));
}
int main() {
int y, n;
while (scanf("%d %d", &y, &n) != EOF) {
int m = 1, d = 0;
while (n--) {
++d;
if (d > month[m][isleap(y)]) {
++m;
d = 1;
}
}
printf("%04d-%02d-%02d\n", y, m, d);
}
return 0;
}
日期类
#include<cstdio>
int month[13][2] = { {0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},
{31,31},{30,30},{31,31},{30,30},{31,31 } };
bool isleap(int year) {
return (year % 400 == 0 || (year % 4 == 0) && (year % 100 != 0));
}
int main() {
int n;
scanf("%d", &n);
while (n--) {
int y, m, d;
scanf("%d %d %d", &y, &m, &d);
++d;
if (d > month[m][isleap(y)]) {
++m;
d = 1;
}
if (m > 12) {
++y;
m = 1;
}
printf("%04d-%02d-%02d\n", y, m, d);
}
return 0;
}
日期累加
#include<cstdio>
int month[13][2] = { {0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},
{31,31},{30,30},{31,31},{30,30},{31,31 } };
bool isleap(int year) {
return (year % 400 == 0 || (year % 4 == 0) && (year % 100 != 0));
}
int main() {
int n;
scanf("%d", &n);
while (n--) {
int y, m, d, past;
scanf("%d %d %d %d", &y, &m, &d, &past);
while (past--) {
++d;
if (d > month[m][isleap(y)]) {
++m;
d = 1;
}
if (m > 12) {
++y;
m = 1;
}
}
printf("%04d-%02d-%02d\n", y, m, d);
}
return 0;
}
《算法笔记》3.5小节——入门模拟->进制转换
Codeup
又一版 A+B
#include<cstdio>
int main() {
long long a, b;
int num[33],m;
while (scanf("%d %lld %lld", &m, &a, &b)){
if (m == 0) break;
long long c = a + b;
int i = 0;
do {
num[i++] = c % m;
c /= m;
} while (c);
for (int j = i - 1;j >= 0;--j) printf("%d", num[j]);
printf("\n");
}
return 0;
}
数制转换
做对此题的关键在于将ABCDEF等字符转换成数字,同时还要熟练掌握进制转换代码。
#include<cstdio>
#include<cstring>
char num[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
int ato10(char c[],int a) {
int l = strlen(c);
int p = 1, n10 = 0;
for (int i = l - 1;i >= 0;--i) {
if (c[i] >= '0' && c[i] <= '9') n10 += (c[i] - '0') * p;
else if (c[i] >= 'a' && c[i] <= 'f') n10 += (c[i] - 'a' + 10) * p;
else n10 += (c[i] - 'A' + 10) * p;
p *= a;
}
return n10;
}
int main() {
int a, b, i = 0;
char n[50];
while (scanf("%d %s %d", &a, &n, &b) != EOF) {
int n10 = ato10(n, a);
char finaln[50];
int k = 0;
do {
finaln[k++] = num[n10 % b];
n10 /= b;
} while (n10);
for (int i = k - 1;i >= 0;--i) printf("%c", finaln[i]);
printf("\n");
}
return 0;
}
进制转换
写了好久,期间重新写了一遍,没写过大整数的题,多写写就会了,噶油;
#include<cstdio>
#include<cstring>
struct bign {
int d[35];
int len;
bign() {
memset(d, 0, sizeof(d));
len = 0;
}
};
bign change(char str[]) {
bign a;
a.len = strlen(str);
for (int i = 0;i < a.len;++i) {
a.d[i] = str[a.len - i - 1] - '0';
}
return a;
}
int main() {
char n[100];
while (scanf("%s", n) != EOF) {
bign a, c;
a = c = change(n);
int n2[100], r = 0, k = 0;
while (a.len != 0) {
for (int i = a.len - 1;i >= 0;--i) {
r = r * 10 + a.d[i];
if (r < 2) c.d[i] = 0;
else {
c.d[i] = r / 2;
r %= 2;
}
}
while (c.d[c.len - 1] == 0) {
c.len--;
}
a = c;
n2[k++] = r;
r = 0;
}
for (int i = k - 1;i >= 0;--i) printf("%d", n2[i]);
printf("\n");
}
return 0;
}
八进制
#include<cstdio>
int main() {
int n;
while (scanf("%d", &n) != EOF) {
int n8[40], k = 0;
do {
n8[k++] = n % 8;
n /= 8;
} while (n);
for (int i = k - 1;i >= 0;--i) printf("%d", n8[i]);
printf("\n");
}
return 0;
}
配套实战指南
PAT B1022 D进制的A+B
#include<cstdio>
int main() {
int a, b, n;
scanf("%d %d %d", &a, &b, &n);
int c = a + b, z[100], i = 0;
do {
z[i++] = c % n;
c /= n;
} while (c);
for (int j = i - 1;j >= 0;--j) {
printf("%d", z[j]);
}
return 0;
}
PAT B1037 在霍格沃茨找零钱
先换算成Knut再进行计算
#include<cstdio>
const int Galleon = 17 * 29;
const int Sickle = 29;
int main() {
int a1, b1, c1;
int a2, b2, c2;
scanf("%d.%d.%d %d.%d.%d", &a1, &b1, &c1, &a2, &b2, &c2);
int change = a2 * Galleon + b2 * Sickle + c2 - a1 * Galleon - b1 * Sickle - c1;
if (change < 0) {
printf("-");
change = -change;
}
printf("%d.%d.%d", change / Galleon, change % Galleon / Sickle, change % Sickle);
return 0;
}
PAT A1019 General Palindromic Number
#include<cstdio>
int main() {
int n, b;
int bn[100], k = 0;
scanf("%d %d", &n, &b);
do {
bn[k++] = n % b;
n /= b;
} while (n);
bool ispalinum=1;
for (int i = 0;i < k / 2;++i) {
if (bn[i] != bn[k - i - 1]) {
ispalinum = 0;
break;
}
}
if (ispalinum == 1) printf("Yes\n");
else printf("No\n");
for (int i = k - 1; i >= 0;--i) {
if (i != k - 1) printf(" ");
printf("%d", bn[i]);
}
return 0;
}
PAT A1027 Colors in Mars
#include<cstdio>
const char decto[13] = { '0','1','2','3','4','5','6','7','8','9','A','B','C' };
int main() {
int R, G, B;
char r13[2], g13[2], b13[2];
scanf("%d%d%d", &R, &G, &B);
for (int i = 0;i < 2;++i) {
r13[i] = decto[R % 13];
g13[i] = decto[G % 13];
b13[i] = decto[B % 13];
R /= 13;
G /= 13;
B /= 13;
}
printf("#");
printf("%c%c%c%c%c%c", r13[1], r13[0], g13[1], g13[0], b13[1], b13[0]);
return 0;
}
PAT A1058 A+B in Hogwarts
本题AC关键在于将所有int改成long long,不能只修改abc,出错原因可能是中间计算过程出现溢出。
#include<cstdio>
const int Galleon = 17 * 29, Sickle = 29;
int main() {
long long g, s, k;
long long a, b;
scanf("%lld.%lld.%lld", &g, &s, &k);
a = g * Galleon + s * Sickle + k;
scanf("%lld.%lld.%lld", &g, &s, &k);
b = g * Galleon + s * Sickle + k;
long long c = a + b;
printf("%lld.%lld.%lld", c / Galleon, c % Galleon / Sickle, c % Sickle);
return 0;
}
《算法笔记》3.6小节——入门模拟->字符串处理
Codeup
字符串连接
不能用就自己写呗。
#include<cstdio>
char strlenth(char str[]);
int main() {
char a[210], b[105];
while (scanf("%s %s", a, b) != EOF) {
int lena = strlenth(a), lenb = strlenth(b);
for (int i = lena;i < lena + lenb;++i) {
a[i] = b[i - lena];
}
a[lena + lenb] = '\0';
printf("%s\n", a);
}
return 0;
}
char strlenth(char str[]) {
int i;
for (i = 0;str[i] != '\0';++i);
return i;
}
首字母大写
gets不能用,别看这题简单,要做对要注意的点还是比较多的。
#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
const int c = 32;
int main() {
string str;
while (getline(cin, str)) {
int len = str.size();
for (int i = 0;i < len;++i) {
if ((i == 0 || str[i - 1] == ' ' || str[i - 1] == '\t' || str[i - 1] == '\r' || str[i - 1] == '\n')
&& str[i] >= 'a' && str[i] <= 'z') str[i] -= c;
}
cout << str << endl;
}
return 0;
}
字符串的查找删除
gets
无法使用,有一行空行使用getline
无法读入,导致出现格式错误,使用其他方式代替gets
不易于匹配Codeup的检测机制,并且此题花费的时间远超其价值,遂放弃之,若有不同的见解,欢迎评论(估计没人看┓( ´∀` )┏)。
#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
int main() {
string key, str;
getline(cin, key);
int keylen = key.size();
while (getline(cin, str)) {
int len = str.size();
for (int i = 0;i < len;++i) {
if (str[i] == ' ');
else if (str[i] == key[0] || str[i] == key[0] + 32 || str[i] == key[0] - 32) {
int k = i + 1, j;
bool same = 1;
for (j = 1;j < keylen && k < len;++j, ++k)
if (str[k] == key[j] || str[k] == key[j] + 32 || str[k] == key[j] - 32);
else {
same = 0;
break;
}
if (same == 1) i = i + keylen - 1;
else printf("%c", str[i]);
}
else printf("%c", str[i]);
if (i == len - 1) printf("\n");
}
}
return 0;
}
单词替换
运行错误,下面是早些年可以通过的代码,我已经几乎是复刻了,本地运行完全没问题,Codeup上还是不行,运行错误,有大佬吗,跪求解释。感觉把char数组全部换成string类型可能可以。
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
using namespace std;
int main() {
string s;
while (getline(cin, s)) {
char a[50], b[50];
char words[100][50];
scanf("%s", a);
scanf("%s", b);
int len = s.size();
int r = 0, h = 0;
for (int i = 0;i < len;++i) {
if (s[i] != ' ') words[r][h++] = s[i];
else {
words[r++][h] = '\0';
h = 0;
}
}
words[r + 1][h] = '\0';
for (int i = 0;i <= r;++i) {
if (strcmp(words[i], a) == 0) printf("%s", b);
else printf("%s", words[i]);
if (i != r) printf(" ");
else printf("\n");
}
getchar();
}
return 0;
}
#include <cstdio>
#include <cstring>
int main() {
char s[120];
while (gets(s)) {
char source[110] = {}, dest[110] = {}, words[110][50] = {};
gets(source);
gets(dest);
int r = 0, c = 0;
for (int i = 0; s[i]; i++) {
if (s[i] != ' ') {
words[r][c++] = s[i];
} else {
words[r++][c] = '\0';
c = 0;
}
}
for (int j = 0; j <= r; j++) {
if (strcmp(words[j], source) == 0) {
printf("%s", dest);
} else {
printf("%s", words[j]);
}
if (j < r) printf(" ");
else printf("\n");
}
}
return 0;
}
字符串去特定字符
s是一个字符串(可能含有’ ')使用while(scanf("%s",s)!=EOF)
会导致答案出错
#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
int main() {
string s;
char c;
while (getline(cin, s)) {
c = getchar();
int len = s.size();
for (int i = 0;i < len;++i) if (s[i] != c) printf("%c", s[i]);
printf("\n");
getchar();
}
return 0;
}
数组逆置
#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
int main() {
string s;
while (getline(cin, s)) {
int len = s.size();
for (int i = len - 1;i >= 0;--i) printf("%c", s[i]);
printf("\n");
}
return 0;
}
比较字符串
#include<cstdio>
#include<cstring>
int main() {
int n;
scanf("%d", &n);
while (n--) {
char a[55], b[55];
scanf("%s %s", a, b);
int lena = strlen(a), lenb = strlen(b);
if (lena > lenb) printf("%s is longer than %s\n", a, b);
else if (lena < lenb) printf("%s is shorter than %s\n", a, b);
else printf("%s is equal long to %s\n", a, b);
}
return 0;
}
编排字符串
#include<cstdio>
#include<cstring>
int main() {
int n;
scanf("%d", &n);
char str[105][25];
for (int i = 0;i < n;++i) {
scanf("%s", str[i]);
int cnt = 1;
for (int j = i;j >= 0 && cnt <= 4;--j) printf("%d=%s ", cnt++, str[j]);
printf("\n");
}
return 0;
}
【字符串】回文串
#include<cstdio>
#include<cstring>
const int maxn = 256;
int main() {
char str[maxn];
while (scanf("%s", str) != EOF) {
int len = strlen(str);
int judge = 1;
for (int i = 0;i < len/2;++i)
if (str[i] != str[len - i - 1]) {
judge = 0;
break;
}
if (judge == 0) printf("NO");
else printf("YES");
printf("\n");
}
return 0;
}
配套实战指南
PAT B1006 换个格式输出整数
#include<cstdio>
int main() {
int n, r = 0, h = 0,k;
char num[3];
scanf("%d", &n);
do {
num[r++] = n % 10;
n /= 10;
} while (n);
for (int i = r - 1;i >= 0;--i) {
if (i == 2)
for (int j = 0;j < num[i];++j) printf("B");
else if (i == 1)
for (int j = 0;j < num[i];++j) printf("S");
else
for (int j = 1;j <= num[i];++j) printf("%d", j);
}
return 0;
}
PAT B1021 个位数统计
#include<cstdio>
#include<cstring>
int main() {
char num[1005];
int ans[10] = { 0 };
scanf("%s", num);
int len = strlen(num);
for (int i = 0;i < len;++i) {
++ans[num[i] - '0'];
}
for (int i = 0;i < 10;++i)
if (ans[i] != 0) {
printf("%d:%d\n", i, ans[i]);
}
return 0;
}
PAT B1031 查验身份证
这是最开始写错的代码,没注意到身份证号里还有字母,竟然AC了,这种写法不好判断内部字母,遂重写。
#include<cstdio>
#include<cstring>
const int weight[17] = { 7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2 };
const char conterpart[11] = { '1','0','X','9','8','7','6','5','4','3','2' };
int main() {
int n;
bool all=1,r[100] = { 0 };
char id[100][19];
scanf("%d", &n);
for (int i = 0;i < n;++i) {
scanf("%s", id[i]);
int sum=0;
for (int j = 0;j < 17;++j) {
sum += (id[i][j] - '0') * weight[j];
}
int z = sum % 11;
if (id[i][17] == conterpart[z]) r[i] = 1;
else all = false;
}
if (all) printf("All passed");
else for (int i = 0;i < n;++i) {
if (!r[i]) printf("%s\n", id[i]);
}
return 0;
}
#include<cstdio>
#include<cstring>
const int w[17] = { 7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2 };
const char cp[11] = { '1','0','X','9','8','7','6','5','4','3','2' };
int main() {
int n;
scanf("%d", &n);
bool flag = true;
char id[20];
for (int i = 0;i < n;++i) {
scanf("%s", id);
int j, sum=0;
for (j = 0;j < 17;++j) {
if (!(id[j] >= '0' && id[j] <= '9')) break;
sum += (w[j] * (id[j] - '0'));
}
if (j < 17) {
flag = false;
printf("%s\n", id);
}
else {
int z = sum % 11;
if (cp[z] != id[17]) {
flag = false;
printf("%s\n", id);
}
}
}
if (flag == true) {
printf("All passed");
}
return 0;
}
PAT B1002 写出这个数
#include<cstdio>
#include<cstring>
char cp[10][5] = { "ling","yi","er","san","si","wu","liu","qi","ba","jiu" };
int main() {
char num[110], res[5];
scanf("%s", num);
int len = strlen(num), sum = 0;
for (int i = 0;i < len;++i) {
sum += num[i] - '0';
}
int i = 0;
do {
res[i++] = sum % 10 + '0';
sum /= 10;
} while (sum);
for (int j = i - 1;j >= 0;--j) {
printf("%s", cp[res[j] - '0']);
if (j != 0) printf(" ");
}
return 0;
}
PAT B1009 说反话
前者是算法笔记上的简洁方法,使用EOF来判断单词是否已经输入完毕。
后者中由于gets无法使用,使用getline代替,函数在头文件#include<string>
中,同时原有的strlen()
无法使用,用str.size()
代替,函数在头文件#include<iostream>
#include<cstdio>
int main() {
int word[90][90];
int num = 0;
while (scanf("%s", word[num]) != EOF) {//不可写成word[num++]
++num;
}
for (int i = num - 1;i >= 0;--i) {
printf("%s", word[i]);
if (i != 0) printf(" ");
}
return 0;
}
#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
int main() {
string str;
char word[90][90];
getline(cin,str);
int len = str.size(),r=0,h=0;
for (int i = 0;i < len;++i) {
if (str[i] != ' ') {
word[r][h++] = str[i];
}
else {
word[r][h] = '\0';
++r;
h = 0;
}
}
for (int i = r ;i >= 0;--i) {
printf("%s", word[i]);
if (i != 0) printf(" ");
}
}
PAT A1061 Dating/B1014 福尔摩斯的约会
要注意的点:首先是字符的范围,星期几范围在A到G,时间是0到9加上A到N。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const char week[7][4] = { "MON","TUE","WED","THU","FRI","SAT","SUN" };
int main() {
char str[4][65];
for (int i = 0;i < 4;++i) scanf("%s", str[i]);
int len = min(strlen(str[0]), strlen(str[1]));
bool t = 0;
for (int i = 0;i < len;++i) {
if (str[0][i] == str[1][i]) {
if ('A' <= str[0][i] && str[0][i] <= 'G' && t == 0) {
printf("%s ", week[str[0][i] - 'A']);
t = 1;
continue;
}
else if ('0' <= str[0][i] && str[0][i] <= '9' && t == 1) {
printf("%02d:", str[0][i] - '0');
break;
}
else if ('A' <= str[0][i] && str[0][i] <= 'N' && t == 1) {
printf("%02d:", str[0][i] - 'A' + 10);
break;
}
}
}
len = min(strlen(str[2]), strlen(str[3]));
for (int i = 0;i < len;++i) {
if ('A' <= str[2][i] && str[2][i] <= 'Z'||'a' <= str[2][i] && str[2][i] <= 'z') {
if (str[2][i] == str[3][i]) {
printf("%02d", i);
break;
}
}
}
return 0;
}
PAT A1073 Scientific Notation/B1024 科学计数法
#include<cstdio>
#include<cstring>
int main() {
char num[10010];
scanf("%s",num);
int el,len=strlen(num),e=0;
for(el=0;el<len&&num[el]!='E';++el);
for(int i=el+2;i<len;++i) e=10*e+(num[i]-'0');
int i=0;
if(num[el+1]=='-'){
if(num[0]=='-') printf("-");
printf("0.");
for(int i=0;i<e-1;++i) printf("0");
for(i=0;num[i]!='E';++i) if(num[i]>='0'&&num[i]<='9') printf("%c",num[i]);
}else{
int cnt=-1;
if(num[0]=='-') printf("-");
for(i=0;num[i]!='E';++i) {
if(num[i]>='0'&&num[i]<='9') {
printf("%c",num[i]);
++cnt;
if(cnt==e&&num[i+1]!='E') printf(".");
}
}
for(;cnt<e;++cnt) printf("0");
}
return 0;
}
PAT B1048 数字加密
书上的倒转算法可能写起来会更简单,这种写法要注意两种过长的处理,漏掉其中任一种都会导致有检查点错误。
#include<cstdio>
#include<cstring>
const char odd[13] = { '0','1','2','3','4','5','6','7','8','9','J','Q','K' };
int main() {
char code[105], num[105], ans[105];
scanf("%s %s", code, num);
int cnt = 0, len1 = strlen(code), len2 = strlen(num);
for (int i = len2 - 1, j = len1 - 1;i >= 0 && j >= 0;--i, --j) {
if (cnt % 2 == 0) {
int sum = (num[i] - '0' + code[j] - '0') % 13;
ans[i] = odd[sum];
++cnt;
}
else {
int res = num[i] - code[j];
if (res < 0) res += 10;
ans[i] = odd[res];
++cnt;
}
}
if (cnt < len2) for (int i = len2 - cnt - 1;i >= 0;--i) {
ans[i] = num[i];
}
else {
int k = len1 - cnt;
code[k] = '\0';
for (int i = k - 1;i >= 0;--i) {
if (cnt % 2 == 1) {
int res = '0' - code[i];
if (res < 0) res += 10;
code[i] = odd[res];
}
++cnt;
}
printf("%s", code);
}
ans[len2] = '\0';
printf("%s", ans);
return 0;
}
PAT A1001 A+B Format
最后的输出语句得注意反向输出的逻辑,另外最后一位不能加‘,’;
#include<cstdio>
#include<cstring>
int main() {
int a, b, c, flag;
scanf("%d %d", &a, &b);
c = a + b;
if (c < 0) {
printf("-");
c = -c;
}
int k = 0;
int num[10];
do {
num[k++] = c % 10;
c /= 10;
} while (c);
for (int i = k - 1;i >= 0;--i) {
printf("%d", num[i]);
if (i % 3 == 0 && i > 0) printf(",");
}
return 0;
}
PAT A1005 Spell It Right
#include<cstdio>
#include<cstring>
const char num[][6] = { "zero","one","two","three","four","five","six","seven","eight","nine" };
int main() {
char n[105];
scanf("%s", n);
int len = strlen(n), sum = 0;
for (int i = 0;i < len;++i) {
sum += (n[i] - '0');
}
int res[5], k = 0;
do {
res[k++] = sum % 10;
sum /= 10;
} while (sum);
for (int i = k - 1;i >= 0;--i) {
printf("%s", num[res[i]]);
if (i) printf(" ");
}
return 0;
}
PAT A1035 Password
#include<cstdio>
#include<cstring>
int main() {
int n, cnt = 0;
bool a = 0;
scanf("%d", &n);
char resname[1010][15], respw[1010][15];
for (int i = 0;i < n;++i) {
bool mis = 0;
char name[15], pw[15];
scanf("%s %s", name, pw);
int len = strlen(pw);
for (int j = 0;j < len;++j) {
if (pw[j] == '1') {
pw[j] = '@';
mis = 1;
}
else if (pw[j] == '0') {
pw[j] = '%';
mis = 1;
}
else if (pw[j] == 'l') {
pw[j] = 'L';
mis = 1;
}
else if (pw[j] == 'O') {
pw[j] = 'o';
mis = 1;
}
}
if (mis == 1) {
strcpy(resname[cnt], name);
strcpy(respw[cnt], pw);
++cnt;
a = 1;
}
}
if (a == 0) {
if (n == 1) printf("There is %d account and no account is modified", n);
else printf("There are %d accounts and no account is modified", n);
}
else {
printf("%d\n", cnt);
for (int i = 0;i < cnt;++i) {
printf("%s %s", resname[i], respw[i]);
if (i != cnt - 1) printf("\n");
}
}
return 0;
}
PAT A1077 Kuchiguse
#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
int main() {
int n, minlen = 257;
scanf("%d", &n);
getchar();
string sen[100];
for (int i = 0;i < n;++i) {
getline(cin, sen[i]);
int len = sen[i].size();
if (len < minlen) minlen = len;
for (int j = 0;j < len / 2;++j) {
char temp = sen[i][j];
sen[i][j] = sen[i][len - j - 1];
sen[i][len - j - 1] = temp;
}
}
bool same = 1;
int i;
for (i = 0;i < minlen;++i) {
for (int j = 1;j < n;++j) {
if (sen[j][i] != sen[0][i]) {
same = 0;
break;
}
}
if (same == 0) break;
}
if (i == 0) printf("nai");
else for (int j = i - 1;j >= 0;--j) printf("%c", sen[0][j]);
return 0;
}
PAT A1082 Read Number in Chinese
约束条件太多,作为第一位输出的之前不能有空格,如果一个数前面的数是0得输出ling,万,十万,百万,千万中存在不为0的数时就要输出Wan,第一次提交都是格式错误,非常搞人心态。花了很长时间才通过所有检查点。
#include<cstdio>
char n[][5] = { "ling","yi","er","san","si","wu","liu","qi","ba","jiu" };
char w[][6] = { "","Shi","Bai","Qian","Wan","Shi","Bai","Qian" };
int main() {
int num;
scanf("%d", &num);
if (num < 0) {
printf("Fu ");
num = -num;
}
char str[10];
int k = 0;
do {
str[k++] = num % 10 + '0';
num /= 10;
} while (num);
bool blank = 0;
for (int i = k - 1;i >= 0;--i) {
if (i == 8 && str[i] != '0') {
printf("%s Yi", n[str[i] - '0']);
blank = 1;
}
else if (i == 4) {
if (str[i] == '0' && !(str[5] == '0' && str[6] == '0' && str[7] == '0')) {
if (blank == 1) printf(" ");
printf("Wan");
}
else if (str[i] != '0') {
if (blank == 1) printf(" ");
if (i + 1 < k && str[i + 1] == '0') printf("ling ");
printf("%s Wan", n[str[i] - '0']);
}
if (!blank) blank = 1;
}
else if (i == 0) {
if (str[i] != '0') {
if (blank == 1) printf(" ");
if (i + 1 < k && str[i + 1] == '0') printf("ling ");
printf("%s", n[str[i] - '0']);
}
}
else {
if (str[i] != '0') {
if (blank == 1) printf(" ");
if (i + 1 < k && str[i + 1] == '0') printf("ling ");
printf("%s %s", n[str[i] - '0'], w[i]);
if (!blank) blank = 1;
}
}
}
if (k == 1 && str[0] == '0') printf("ling");
return 0;
}
《算法笔记》4.1小节——算法初步->排序
Codeup
排序
#include<stdio.h>
#include<algorithm>
using namespace std;
int main() {
int n;
while (scanf("%d", &n) != EOF) {
int num[105];
for (int i = 0;i < n;++i) scanf("%d", &num[i]);
sort(num, num + n);
for (int i = 0;i < n;++i) printf("%d ", num[i]);
printf("\n");
}
return 0;
}
特殊排序
#include<stdio.h>
#include<algorithm>
using namespace std;
int main() {
int n;
while (scanf("%d", &n) != EOF) {
int num[1010];
for (int i = 0;i < n;++i) scanf("%d", &num[i]);
sort(num, num + n);
printf("%d\n", num[n - 1]);
if (n == 1) printf("-1");
else for (int i = 0;i < n - 1;++i) printf("%d ", num[i]);
printf("\n");
}
return 0;
}
EXCEL排序
我还以为输出的Case是排序方式的值呢。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Student {
int id;
char name[10];
int grade;
}stus[100010];
bool cmp1(Student a, Student b) {
return a.id < b.id;
}
bool cmp2(Student a, Student b) {
if (strcmp(a.name, b.name)) return strcmp(a.name, b.name) < 0;
else return a.id < b.id;
}
bool cmp3(Student a, Student b) {
if (a.grade != b.grade) return a.grade < b.grade;
else return a.id < b.id;
}
int main() {
int n, count = 0;
while (scanf("%d", &n) != EOF && n != 0) {
int c;
scanf("%d", &c);
int id;
for (int i = 0;i < n;++i)
scanf("%d %s %d", &stus[i].id, &stus[i].name, &stus[i].grade);
switch (c) {
case 1: {
sort(stus, stus + n, cmp1);
break;
}
case 2: {
sort(stus, stus + n, cmp2);
break;
}
case 3: {
sort(stus, stus + n, cmp3);
break;
}
}
printf("Case %d:\n", ++count);
for (int i = 0;i < n;++i)
printf("%06d %s %d\n", stus[i].id, stus[i].name, stus[i].grade);
}
return 0;
}
字符串内排序
#include<cstdio>
#include<algorithm>
#include<string>
#include<iostream>
using namespace std;
bool cmp(char a, char b) {
return a < b;
}
int main() {
string str;
while (getline(cin, str)) {
int len = str.size();
char c[210];
for (int i = 0;i < len;++i) c[i] = str[i];
c[len] = '\0';
sort(c, c + len, cmp);
printf("%s\n", c);
}
return 0;
}
Problem B
#include<cstdio>
#include<algorithm>
using namespace std;
bool cmp(int a, int b) {
return a > b;
}
int main() {
int n;
while (scanf("%d", &n) != EOF) {
int res[25] = { 0 }, k = 0, in[11][11] = { 0 };
for (int i = 0;i < n;++i) {
int sumi = 0;
for (int j = 0;j < n;++j) {
scanf("%d", &in[i][j]);
sumi += in[i][j];
}
res[k++] = sumi;
}
for (int i = 0;i < n;++i) {
int sumj = 0;
for (int j = 0;j < n;++j) {
sumj += in[j][i];
}
res[k++] = sumj;
}
for (int i = 0, j = 0;i < n && j < n;++i, ++j) {
res[k] += in[i][j];
res[k + 1] += in[i][n - i - 1];
}
k += 2;
sort(res, res + k, cmp);
for (int i = 0;i < k;++i) {
printf("%d", res[i]);
if (i != k - 1) printf(" ");
else printf("\n");
}
}
return 0;
}
小白鼠排队
#include<cstdio>
#include<algorithm>
using namespace std;
struct mouse {
int weight;
char color[15];
}m[105];
bool cmp(mouse a, mouse b) {
return a.weight > b.weight;
}
int main() {
int n;
while (scanf("%d", &n) != EOF) {
for (int i = 0;i < n;++i) {
scanf("%d %s", &m[i].weight, m[i].color);
}
sort(m, m + n, cmp);
for (int i = 0;i < n;++i) {
printf("%s\n", m[i].color);
}
}
return 0;
}
中位数
#include<cstdio>
#include<algorithm>
using namespace std;
int main() {
int n;
while (scanf("%d", &n) != EOF && n) {
int num[10010];
for (int i = 0;i < n;++i) scanf("%d", &num[i]);
sort(num, num + n);
if (n % 2) printf("%d\n", num[n / 2]);
else printf("%d\n", (num[n / 2 - 1] + num[n / 2]) / 2);
}
return 0;
}
整数奇偶排序
#include<cstdio>
#include<algorithm>
using namespace std;
bool cmp(int a, int b) {
if (a % 2 != b % 2) return a % 2 > b % 2;
else if (a % 2 == b % 2 && a % 2 == 1) return a > b;
else if (a % 2 == b % 2 && a % 2 == 0) return a < b;
}
int main() {
int a[15];
while (scanf("%d %d %d %d %d %d %d %d %d %d",
&a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7], &a[8], &a[9]) != EOF) {
sort(a, a + 10, cmp);
for (int i = 0;i < 10;++i) {
printf("%d", a[i]);
if (i == 9) printf("\n");
else printf(" ");
}
}
return 0;
}
排名
#include<cstdio>
#include<algorithm>
using namespace std;
struct Student {
char id[25];
bool a[6] = { 0 };
int grade = 0;
}stus[1010];
bool cmp(Student a, Student b) {
return a.grade > b.grade;
}
int main() {
int n, m, g;
while (scanf("%d %d %d", &n, &m, &g) && n) {
int score[12], cnt = 0;
for (int i = 1;i <= m;++i) scanf("%d", &score[i]);
for (int i = 0;i < n;++i) {
int k;
scanf("%s %d", stus[i].id, &k);
for (int j = 0;j < k;++j) {
int z;
scanf("%d", &z);
stus[i].a[z] = 1;
stus[i].grade += stus[i].a[z] * score[z];
}
if (stus[i].grade >= g) ++cnt;
}
sort(stus, stus + n, cmp);
printf("%d\n", cnt);
for (int i = 0;i < cnt;++i) {
printf("%s %d\n", stus[i].id, stus[i].grade);
}
}
return 0;
}
配套实战指南
PAT A1062 Talent and Virtue/B1015 德才论
注意审题,另注意可以将int型flag放入struct中,方便比较。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct People {
char id[10];
int vg, tg, total;
int flag;
}people[100005];
bool cmp(People a, People b) {
if (a.flag != b.flag) return a.flag < b.flag;
else if (a.total != b.total) return a.total > b.total;
else if (a.vg != b.vg) return a.vg > b.vg;
else return strcmp(a.id, b.id) < 0;
}
int main() {
int n, m, l, h;
scanf("%d %d %d", &n, &l, &h);
m = n;
for (int i = 0;i < n;++i) {
scanf("%s %d %d", people[i].id, &people[i].vg, &people[i].tg);
people[i].total = people[i].vg + people[i].tg;
if (people[i].vg < l || people[i].tg < l) {
people[i].flag = 5;
--m;
}
else if (people[i].vg >= h && people[i].tg >= h) people[i].flag = 1;
else if (people[i].tg < h && people[i].vg >= h) people[i].flag = 2;
else if (people[i].vg < h && people[i].tg < h && people[i].vg >= people[i].tg) people[i].flag = 3;
else people[i].flag = 4;
}
printf("%d\n", m);
sort(people, people + n, cmp);
for (int i = 0;i < m;++i) {
printf("%s %d %d", people[i].id, people[i].vg, people[i].tg);
if (i != m - 1) printf("\n");
}
return 0;
}
PAT A1012 The Best Rank
写了好久,裂开来,各种bug。round函数在#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
char course[4] = { 'A','C','M','E' };
int now;
struct student {
int id;
int grade[4];
int rank[4];
}stus[2010];
bool cmp(student a, student b) {
return a.grade[now] > b.grade[now];
}
int main() {
int n, m;
scanf("%d %d", &n, &m);
for (int i = 0;i < n;++i) {
scanf("%d %d %d %d", &stus[i].id, &stus[i].grade[1], &stus[i].grade[2], &stus[i].grade[3]);
stus[i].grade[0] = round(stus[i].grade[1] + stus[i].grade[2] + stus[i].grade[3]) / 3.0;
}
for (now = 0;now < 4;++now) {
sort(stus, stus + n, cmp);
for (int i = 0;i < n;++i) {
if (i > 0 && stus[i].grade[now] == stus[i - 1].grade[now]) stus[i].rank[now] = stus[i - 1].rank[now];
else stus[i].rank[now] = i + 1;
}
}
for (int i = 0;i < m;++i) {
int search;
int min = 5, l = -1;
scanf("%d", &search);
int same = 0;
for (int j = 0;j < n;++j) {
if (stus[j].id == search) {
same = 1;
for (int k = 0;k < 4;++k) {
if (stus[j].rank[k] < min) {
min = stus[j].rank[k];
l = k;
}
}
printf("%d %c\n", min, course[l]);
}
if (j == n - 1 && same == 0) printf("N/A\n");
}
}
return 0;
}
PAT A1016 Phone Bills
整整写了三小时,只对了第一个检查点,然后找了很久的问题,找不到,自己测试感觉没啥检查点情况会出问题的,于是手写了一下晴神的原版代码,发现都能过,改了很久还是没找出问题所在。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int charge[25];
struct record {
char name[25];
int t[4];
bool status;
}rec[1010];
bool cmp(record a, record b);
void get_tm(record a, record b, int& time, int& money);
int main() {
for (int i = 0;i < 24;++i) scanf("%d", &charge[i]);
int n;
scanf("%d", &n);
for (int i = 0;i < n;++i) {
char temp[10];
scanf("%s %d:%d:%d:%d %s", rec[i].name, &rec[i].t[0], &rec[i].t[1], &rec[i].t[2], &rec[i].t[3], temp);
if (strcmp(temp, "on-line") == 0) rec[i].status = 1;
else rec[i].status = 0;
}
sort(rec, rec + n, cmp);
int i = 0, next;
while (i < n) {
int needPrint = 0;
next = i;
while (next < n && strcmp(rec[next].name, rec[i].name) == 0) {
if (needPrint == 0 && rec[next].status == 1) needPrint = 1;
else if (needPrint == 1 && rec[next].status == 0) needPrint = 2;
++next;
}
if (needPrint < 2) {
i = next;
}
else {
int Allmoney = 0;
printf("%s %02d\n", rec[i].name, rec[i].t[0]);
while (i < next) {
if (rec[i].name != rec[i - 1].name && i > 0 && rec[i].status == false && rec[i - 1].status == true) {
printf("%02d:%02d:%02d ", rec[i - 1].t[1], rec[i - 1].t[2], rec[i - 1].t[3]);
printf("%02d:%02d:%02d ", rec[i].t[1], rec[i].t[2], rec[i].t[3]);
int time = 0, money = 0;
get_tm(rec[i - 1], rec[i], time, money);
Allmoney += money;
printf("%d $%.2f\n", time, money / 100.0);
}
++i;
}
printf("Total amount: $%.2f\n", Allmoney / 100.0);
}
}
return 0;
}
bool cmp(record a, record b) {
if (strcmp(a.name, b.name) != 0) return strcmp(a.name, b.name) < 0;
else for (int i = 0;i < 4;++i) if (a.t[i] != b.t[i]) return a.t[i] < b.t[i];
}
void get_tm(record a, record b, int& time, int& money) {
while (a.t[1] < b.t[1] || a.t[2] < b.t[2] || a.t[3] < b.t[3]) {
++time;
money += charge[a.t[2]];
++a.t[3];
if (a.t[3] >= 60) {
a.t[3] = 0;
++a.t[2];
}
if (a.t[2] >= 24) {
a.t[2] = 0;
++a.t[1];
}
}
}
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1010;
int toll[25];
struct Record {
char name[25];
int month, dd, hh, mm;
bool status;
}rec[maxn], temp;
bool cmp(Record a, Record b) {
int s = strcmp(a.name, b.name);
if (s != 0) return s < 0;
else if (a.month != b.month) return a.month < b.month;
else if (a.dd != b.dd) return a.dd < b.dd;
else if (a.hh != b.hh) return a.hh < b.hh;
else return a.mm < b.mm;
}
void get_ans(int on, int off, int& time, int& money) {
temp = rec[on];
while (temp.dd < rec[off].dd || temp.hh < rec[off].hh || temp.mm < rec[off].mm) {
time++;
money += toll[temp.hh];
temp.mm++;
if (temp.mm >= 60) {
temp.mm = 0;
temp.hh++;
}
if (temp.hh >= 24) {
temp.hh = 0;
temp.dd++;
}
}
}
int main() {
for (int i = 0;i < 24;i++) {
scanf("%d", &toll[i]);
}
int n;
scanf("%d", &n);
char line[10];
for (int i = 0;i < n;++i) {
scanf("%s", rec[i].name);
scanf("%d:%d:%d:%d", &rec[i].month, &rec[i].dd, &rec[i].hh, &rec[i].mm);
scanf("%s", line);
if (strcmp(line, "on-line") == 0) {
rec[i].status = true;
}
else {
rec[i].status = false;
}
}
sort(rec, rec + n, cmp);
int on = 0, off, next;
while (on < n) {
int needPrint = 0;
next = on;
while (next < n && strcmp(rec[next].name, rec[on].name) == 0) {
if (needPrint == 0 && rec[next].status == true) {
needPrint = 1;
}
else if (needPrint == 1 && rec[next].status == false) {
needPrint = 2;
}
next++;
}
if (needPrint < 2) {
on = next;
continue;
}
int AllMoney = 0;
printf("%s %02d\n", rec[on].name, rec[on].month);
while (on < next) {
while(on<next-1&&!(rec[on].status==true&&rec[on+1].status==false)) {
on++;
}
off = on + 1;
if (off == next) {
on = next;
break;
}
printf("%02d:%02d:%02d ", rec[on].dd, rec[on].hh, rec[on].mm);
printf("%02d:%02d:%02d ", rec[off].dd, rec[off].hh, rec[off].mm);
int time = 0,money = 0;
get_ans(on, off, time, money);
AllMoney += money;
printf("%d $%.2f\n", time, money / 100.0);
on = off + 1;
}
printf("Total amount: $%.2f\n", AllMoney / 100.0);
}
return 0;
}
PAT A1025 PAT Ranking
第一次写一遍过还是有点惊喜,要注意的是sort(stus, stus + sn, cmp);
不能写成sort(stus[0], stus[sn], cmp);
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Student {
char num[14];
int grade, fr, ln, lr;
}stus[30010];
bool cmp(Student a, Student b);
int main() {
int n, sn = 0;
scanf("%d", &n);
for (int i = 0;i < n;++i) {
int k;
scanf("%d", &k);
int m = sn;
for (int j = 0;j < k;++j) {
scanf("%s %d", stus[sn].num, &stus[sn].grade);
stus[sn].ln = i + 1;
++sn;
}
sort(stus + m, stus + sn, cmp);
for (int i = m;i < sn;++i) {
if (i > m && stus[i].grade == stus[i - 1].grade) {
stus[i].lr = stus[i - 1].lr;
}
else stus[i].lr = i + 1 - m;
}
}
printf("%d\n", sn);
sort(stus, stus + sn, cmp);
for (int i = 0;i < sn;++i) {
if (i > 0 && stus[i].grade == stus[i - 1].grade) {
stus[i].fr = stus[i - 1].fr;
}
else stus[i].fr = i + 1;
printf("%s %d %d %d", stus[i].num, stus[i].fr, stus[i].ln, stus[i].lr);
if (i != sn - 1) printf("\n");
}
return 0;
}
bool cmp(Student a, Student b) {
if (a.grade != b.grade) return a.grade > b.grade;
else return strcmp(a.num, b.num) < 0;
}
PAT A1028 List Sorting
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Student {
int id;
char name[10];
int grade;
}stus[100010];
bool cmp1(Student a, Student b) {
return a.id < b.id;
}
bool cmp2(Student a, Student b) {
if (strcmp(a.name, b.name)) return strcmp(a.name, b.name) < 0;
else return a.id < b.id;
}
bool cmp3(Student a, Student b) {
if (a.grade != b.grade) return a.grade < b.grade;
else return a.id < b.id;
}
int main() {
int n, count = 0;
while (scanf("%d", &n) != EOF && n != 0) {
int c;
scanf("%d", &c);
int id;
for (int i = 0;i < n;++i)
scanf("%d %s %d", &stus[i].id, &stus[i].name, &stus[i].grade);
switch (c) {
case 1: {
sort(stus, stus + n, cmp1);
break;
}
case 2: {
sort(stus, stus + n, cmp2);
break;
}
case 3: {
sort(stus, stus + n, cmp3);
break;
}
}
for (int i = 0;i < n;++i)
printf("%06d %s %d\n", stus[i].id, stus[i].name, stus[i].grade);
}
return 0;
}
PAT A1055 The World’s Richest
晴神的代码中预处理了相同年龄人的个数,用数组valid[]存储相同年龄100名以内的数据。但规定的时间为500ms,完成检测点2只用了不到300ms,因此未增加预处理。
int Age[maxn] = { 0 };
int validNum = 0;
for (int i = 0;i < n;++i) {
if (Age[bn[i].age] < 100) {
++Age[bn[i].age];
valid[validNum] = ps[i];
}
}
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct billionaire {
char name[10];
int age, worth;
}bn[100010];
bool cmp(billionaire a, billionaire b) {
if (a.worth != b.worth) return a.worth > b.worth;
else if (a.age != b.age) return a.age < b.age;
else return strcmp(a.name, b.name) < 0;
}
int main() {
int n, k;
scanf("%d %d", &n, &k);
for (int i = 0;i < n;++i) scanf("%s %d %d", bn[i].name, &bn[i].age, &bn[i].worth);
sort(bn, bn + n, cmp);
for (int i = 0;i < k;++i) {
int m, amin, amax, cnt = 0;
bool is = 0;
scanf("%d %d %d", &m, &amin, &amax);
printf("Case #%d:\n", i + 1);
for (int j = 0;cnt < m && j < n;++j) {
if (bn[j].age >= amin && bn[j].age <= amax) {
printf("%s %d %d\n", bn[j].name, bn[j].age, bn[j].worth);
is = 1;
++cnt;
}
}
if (is == 0) printf("None\n");
}
return 0;
}
PAT A1075 PAT Judge
最后一个检查点超时,原因未知。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct User {
int id, ps[6] = { 0,-1,-1,-1,-1,-1 }, ts = 0, psp = 0, r;
bool canprint = 0;
}u[10000];
bool cmp(User a, User b) {
if (a.ts != b.ts) return a.ts > b.ts;
else if (a.psp != b.psp) return a.psp > b.psp;
else return a.id < b.id;
}
int main() {
int n, k, m;
scanf("%d %d %d", &n, &k, &m);
int p[6], cnt = 0;
for (int i = 1;i <= k;++i) scanf("%d", &p[i]);
for (int i = 0;i < m;++i) {
bool same = 0;
int ti, j;
scanf("%d", &ti);
for (j = 0;j <= cnt;++j) {
if (ti == u[j].id) {
same = 1;
break;
}
}
int tempps, tempts;
if (same == 0) {
u[cnt].id = ti;
scanf("%d %d", &tempps, &tempts);
if (tempts != -1) {
u[cnt].ps[tempps] = tempts;
if (tempts == p[tempps]) ++u[j].psp;
u[cnt].ts += tempts;
u[cnt].canprint = 1;
}
else {
u[cnt].ps[tempps] = 0;
}
++cnt;
}
else {
scanf("%d %d", &tempps, &tempts);
if (tempts == -1 && u[j].ps[tempps] == -1) u[j].ps[tempps] = 0;
if (u[j].ps[tempps] < tempts) {
u[j].canprint = 1;
if (tempts == p[tempps]) ++u[j].psp;
if (u[j].ps[tempps] == -1) u[j].ts += tempts;
else u[j].ts += (tempts - u[j].ps[tempps]);
u[j].ps[tempps] = tempts;
}
}
}
sort(u, u + cnt, cmp);
for (int i = 0;i < cnt;++i) {
if (u[i].canprint == 1) {
if (i > 0 && u[i].ts == u[i - 1].ts) u[i].r = u[i - 1].r;
else u[i].r = i + 1;
printf("%d %05d ", u[i].r, u[i].id);
printf("%d ", u[i].ts);
for (int j = 1;j <= k;++j) {
if (u[i].ps[j] == -1) printf("-");
else printf("%d", u[i].ps[j]);
if (j != k) printf(" ");
}
printf("\n");
}
}
return 0;
}
PAT A1083 List Grades
#include<cstdio>
#include<algorithm>
using namespace std;
struct Student {
char name[12];
char id[12];
int grade;
}stus[55];
bool cmp(Student a, Student b) {
return a.grade > b.grade;
}
int main() {
int n;
scanf("%d", &n);
for (int i = 0;i < n;++i) scanf("%s %s %d", stus[i].name, stus[i].id, &stus[i].grade);
int g1, g2;
scanf("%d %d", &g1, &g2);
sort(stus, stus + n, cmp);
int cnt = 0;
for (int i = 0;i < n;++i) {
if (stus[i].grade >= g1 && stus[i].grade <= g2) {
printf("%s %s\n", stus[i].name, stus[i].id);
++cnt;
}
}
if (cnt == 0) {
printf("NONE");
}
return 0;
}
PAT A1080 Graduate Admission
检查点2,3未通过,找不出错误,每次都是错一些网上没人错过的方式,对着晴神宝典也找不出错误,很离谱,很烦躁。
#include<cstdio>
#include<algorithm>
using namespace std;
struct Applicant {
int id;
int ge, gi;//入学考试和面试
int final;
int choice[5];
}apt[40010];
struct school {
int number;//需要的人数
int get[40010];
}sch[105];
bool cmp(Applicant a, Applicant b) {
if (a.final != b.final) return a.final > b.final;
else return a.ge > b.ge;
}
int main() {
int n, m, k; //考生人数,学校数,志愿数
scanf("%d %d %d", &n, &m, &k);
for (int i = 0;i < m;++i) scanf("%d", &sch[i].number);
for (int i = 0;i < n;++i) {
scanf("%d %d", &apt[i].ge, &apt[i].gi);
apt[i].final = (apt[i].ge + apt[i].gi) / 2;
apt[i].id = i;
for (int j = 0;j < k;++j) scanf("%d", &apt[i].choice[j]);
}
sort(apt, apt + n, cmp);
int havein[105] = { 0 }; //存放学校已收人数
for (int i = 0;i < n;++i) {
for (int j = 0;j < k;++j) {
int c = apt[i].choice[j];
if (havein[c] > 0 && apt[i].final == apt[sch[c].get[havein[c] - 1]].final &&
apt[i].ge == apt[sch[c].get[havein[c] - 1]].ge) { //如果和前一个人分数一样 ,破格录取
if (sch[c].number != 0) {
--sch[c].number;
}
sch[c].get[havein[c]++] = apt[i].id;
break;
}
else if (sch[c].number > 0) {
--sch[c].number;
sch[c].get[havein[c]++] = apt[i].id;
break;
}
}
}
for (int i = 0;i < m;++i) {
sort(sch[i].get, sch[i].get + havein[i]);//排序
for (int j = 0;j < havein[i];++j) {
if (j != 0) printf(" ");
printf("%d", sch[i].get[j]);
}
printf("\n");
}
return 0;
}
《算法笔记》4.2小节——算法初步->哈希
Codeup
谁是你的潜在朋友
#include<cstdio>
int main() {
int n, m;
while (scanf("%d %d", &n, &m) != EOF) {
int book[210] = { 0 }, reader[210] = { 0 };
for (int i = 0;i < n;++i) {
int temp;
scanf("%d", &temp);
reader[i] = temp;
++book[temp];
}
for (int i = 0;i < n;++i) {
if (book[reader[i]] == 1) printf("BeiJu");
else printf("%d", book[reader[i]] - 1);
printf("\n");
}
}
return 0;
}
分组统计
说是n<=100,实际上范围可能很大,第一次提交运行出错,然后扩大了exist数组的容量,修改了数组a的范围才行(竟然可以用变量声明数组,奇怪哉,不使用又会因为不清楚数据多少而导致内存超限,建议说清楚来)
#include<cstdio>
int main() {
int m;
scanf("%d", &m);
for (int i = 0;i < m;++i) {
int n;
scanf("%d", &n);
bool exist[10010] = { false }, cexist[10010] = { false };
int b[110], c, max;
for (int j = 0;j < n;++j) {
scanf("%d", &b[j]);
exist[b[j]] = 1;
if (b[j] > max) max = b[j];
}
int a[n + 10][max + 10] = { 0 };
for (int j = 0;j < n;++j) {
scanf("%d", &c);
cexist[c] = 1;
++a[c][b[j]];
}
int num[120] = { 0 }, cnum[120] = { 0 }, cnt = 0, ccnt = 0;
for (int j = 0;j < 10010;++j) {
if (exist[j] == true) num[cnt++] = j;
if (cexist[j] == true) cnum[ccnt++] = j;
}
for (int j = 0;j < ccnt;++j) {
//1={2=0,3=2,8=1}
printf("%d={", cnum[j]);
for (int k = 0;k < cnt;++k) {
if (k != 0) printf(",");
printf("%d=%d", num[k], a[cnum[j]][num[k]]);
}
printf("}\n");
}
}
return 0;
}
Be Unique (20)
#include<cstdio>
int main() {
int n;
scanf("%d", &n);
int num[100010], hashTable[10010] = { 0 };
for (int i = 0;i < n;++i) {
scanf("%d", &num[i]);
++hashTable[num[i]];
}
bool print = false;
for (int i = 0;i < n;++i) {
if (hashTable[num[i]] == 1) {
printf("%d\n", num[i]);
print = true;
break;
}
}
if (print == false) printf("None\n");
return 0;
}
String Subtraction (20)
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
using namespace std;
int main() {
string str1, str2;
bool hashTable[128];
memset(hashTable, true, sizeof(hashTable));
getline(cin, str1);
getline(cin, str2);
int len1 = str1.size(), len2 = str2.size();
for (int i = 0;i < len2;++i) hashTable[str2[i]] = false;
for (int i = 0;i < len1;++i)
if (hashTable[str1[i]] == true)
printf("%c", str1[i]);
return 0;
}
配套实战指南
PAT A1084 Broken Keyboard/B1029 旧键盘
用print散列记录坏键是否输出,大小128刚好覆盖所有ASCII码
#include<cstdio>
#include<cstring>
int main() {
char str1[85], str2[85];
scanf("%s\n%s", str1, str2);
bool print[128] = { false };
int len1 = strlen(str1), len2 = strlen(str2);
int j = 0;
for (int i = 0;i < len1;++i) {
if (str1[i] != str2[j]) {
if ((str1[i] >= 'a' && str1[i] <= 'z' && print[str1[i] - 32] == true) || (print[str1[i]] == true)) continue;
else {
if (str1[i] >= 'a' && str1[i] <= 'z') {
printf("%c", str1[i] - 32);
print[str1[i] - 32] = true;
}
else {
printf("%c", str1[i]);
print[str1[i]] = true;
}
}
}
else ++j;
}
return 0;
}
PAT B1033 旧键盘打字
一开始用scanf检查点2无法通过,网上查了查发现是由于
题目“题目保证第 2 行输入的文字串非空。”就是说第一个字符串可以输入空集。所以第一个字符串的输入得用getline
#include<cstdio>
#include<iostream>
#include<string>
using namespace std;
int main() {
string str;
bool hashTable[128];
memset(hashTable, true, sizeof(hashTable));
getline(cin, str);
int len = str.size();
for (int i = 0;i < len;++i) hashTable[str[i]] = false;
getline(cin, str);
len = str.size();
for (int i = 0;i < len;++i) {
if (str[i] >= 'A' && str[i] <= 'Z') {
if (hashTable['+'] == true && hashTable[str[i]] == true)
printf("%c", str[i]);
}
else if (str[i] >= 'a' && str[i] <= 'z') {
if (hashTable[str[i] - 32] == true)
printf("%c", str[i]);
}
else {
if (hashTable[str[i]] == true)
printf("%c", str[i]);
}
}
printf("\n");
return 0;
}
PAT B1038 统计同成绩学生
#include<cstdio>
int main() {
int n;
scanf("%d", &n);
int hashTable[110] = { 0 };
while (n--) {
int temp;
scanf("%d", &temp);
++hashTable[temp];
}
scanf("%d", &n);
while (n--) {
int temp;
scanf("%d", &temp);
printf("%d", hashTable[temp]);
if (n > 0) printf(" ");
}
printf("\n");
return 0;
}
PAT B1092 To Buy or Not to Buy
NO,‘O’大写了改错改了半天…
#include<cstdio>
#include<cstring>
int main() {
char str1[1010], str2[1010];
scanf("%s", str1);
int hashTable[128] = { 0 };
int len1 = strlen(str1), cnt = 0;
for (int i = 0;i < len1;++i)
++hashTable[str1[i]];
scanf("%s", str2);
int len2 = strlen(str2);
for (int i = 0;i < len2;++i) {
--hashTable[str2[i]];
if (hashTable[str2[i]] < 0)
++cnt;
}
if (cnt > 0) printf("No %d\n", cnt);
else printf("Yes %d\n", len1 - len2);
return 0;
}
PAT B1042 字符统计
#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
int main() {
string str;
int hashTable[128] = { 0 };
getline(cin, str);
int len = str.size(), max = -1, n;
for (int i = 0;i < len;++i) {
if (str[i] >= 'A' && str[i] <= 'Z') str[i] += 32;//转换成小写字母
if (str[i] >= 'a' && str[i] <= 'z') ++hashTable[str[i]];
if (hashTable[str[i]] > max || (hashTable[str[i]] == max && str[i] < n)) {//记录数组中最大的元素的下标,还有可能是字母序小的
max = hashTable[str[i]];
n = str[i];
}
}
printf("%c %d", n, max);
return 0;
}
PAT B1043 输出PATest
#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
char dict[6] = { 'P','A','T','e','s','t' };
int main() {
string str;
int hashTable[6] = { 0 }, cnt = 0;
getline(cin, str);
int len = str.size();
for (int i = 0;i < len;++i) {
for (int j = 0;j < 6;++j) {
if (str[i] == dict[j]) {
++hashTable[j];
++cnt;
break;
}
}
}
for (int i = 0, j = 0;i < cnt;j = (j + 1) % 6) {
--hashTable[j];
if (hashTable[j] >= 0) {
printf("%c", dict[j]);
++i;
}
}
return 0;
}
PAT B1047 编程团体赛
#include<cstdio>
int main() {
int n;
scanf("%d", &n);
int hashTable[1010] = { 0 }, maxt = 0;
while (n--) {
int tno, id, grade;
scanf("%d-%d %d", &tno, &id, &grade);
hashTable[tno] += grade;
if (tno > maxt) maxt = tno;
}
int max = -1, team;//最高分数,队伍号数
for (int i = 0;i <= maxt;++i) {
if (hashTable[i] > max) {
max = hashTable[i];
team = i;
}
}
printf("%d %d", team, max);
return 0;
}
PAT A1041 Be Unique
#include<cstdio>
int main() {
int n;
scanf("%d", &n);
int num[100010], hashTable[10010] = { 0 };
for (int i = 0;i < n;++i) {
scanf("%d", &num[i]);
++hashTable[num[i]];
}
bool print = false;
for (int i = 0;i < n;++i) {
if (hashTable[num[i]] == 1) {
printf("%d\n", num[i]);
print = true;
break;
}
}
if (print == false) printf("None\n");
return 0;
}
PAT A1050String Subtraction
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
using namespace std;
int main() {
string str1, str2;
bool hashTable[128];
memset(hashTable, true, sizeof(hashTable));
getline(cin, str1);
getline(cin, str2);
int len1 = str1.size(), len2 = str2.size();
for (int i = 0;i < len2;++i) hashTable[str2[i]] = false;
for (int i = 0;i < len1;++i)
if (hashTable[str1[i]] == true)
printf("%c", str1[i]);
return 0;
}
PAT B1005 继续(3n+1)猜想
#include<cstdio>
#include<algorithm>
using namespace std;
bool cmp(int a, int b) {
return a > b;
}
int main() {
bool hashTable[10000] = { false };
int n;
scanf("%d", &n);
int num[110];
for (int i = 0;i < n;++i) {
int temp;
scanf("%d", &num[i]);
temp = num[i];
while (temp != 1 && hashTable[num[i]] == false) {//已经被覆盖的数无需再进行计算
if (temp % 2 == 0) {
temp /= 2;
hashTable[temp] = true;
}
else {
temp = (3 * temp + 1) / 2;
hashTable[temp] = true;
}
}
}
sort(num, num + n, cmp);
int f = 0;
for (int i = 0;i < n;++i) {
if (hashTable[num[i]] == false) {
if (f != 0) printf(" ");
printf("%d", num[i]);
++f;
}
}
printf("\n");
return 0;
}
PAT A1048 Find Coins(哈希解法)
虽然是道简单题,但是改错误还是改了好久,首先是粗心导致输出值Solution忘记大写,其次是第二个for循环中的判断条件要写成i<m而不能将m改成其他量,测试发现可能是m可能为0,使用其他值时会导致输出负数。(不懂hashTable[-2]
为什么等于1)
#include<cstdio>
#include<algorithm>
using namespace std;
int main() {
int n, m;
scanf("%d %d", &n, &m);
int coin;
int hashTable[501] = { 0 };
for (int i = 0;i < n;++i) {
scanf("%d", &coin);
if (coin < 501) ++hashTable[coin];
}
bool print = false;
for (int i = 1;i < m;++i) {
if (i < 501 && m - i < 501) {
if (hashTable[i] > 0 && hashTable[m - i] > 0) {
if (i == m - i && hashTable[i] <= 1) continue; //这种情况需要特判是否拥有两枚一样价格的硬币
printf("%d %d\n", i, m - i);
print = true;
break;
}
}
}
if (print == false) printf("No Solution\n");
return 0;
}
《算法笔记》4.3小节——算法初步->递归
吃糖果
本题采用递归的方法假定前n-1天已经吃完,第n天可吃1个或2个。
#include<cstdio>
int cnt = 0;
void generateP(int index) {
if (index == 1 || index == 0) {
++cnt;
return;
}
generateP(index - 1);
generateP(index - 2);
}
int main() {
int n;
while (scanf("%d", &n) != EOF) {
cnt = 0;
generateP(n);
printf("%d\n", cnt);
}
return 0;
}
题目里好像暗示的是用斐波那锲数列的算法
#include<cstdio>
int a[30] = { 0,1,2 };
int main() {
for (int i = 3;i < 30;++i) a[i] = a[i - 1] + a[i - 2];
int n;
while (scanf("%d", &n) != EOF) {
printf("%d\n", a[n]);
}
return 0;
}
数列
#include<cstdio>
int a[30] = { 0,1,1 };
int main() {
for (int i = 3;i < 30;++i) a[i] = a[i - 1] + a[i - 2];
int n, m, cnt = 1;
scanf("%d", &n);
while (n--) {
scanf("%d", &m);
cnt = 1;
while (m--) {
for (int i = 0;i < 2 * m;++i) printf(" ");
for (int i = 0;i < cnt;++i) {
if (i) printf(" ");
printf("%d", a[i]);
}
printf("\n");
cnt += 2;
}
}
return 0;
}
神奇的口袋
#include<cstdio>
int a[30], cnt = 0, n;
void getans(int index, int sum) {
if (sum == 40) {
++cnt;
return;
}
for (int i = index;i < n;++i) {
if (sum + a[i] > 40) continue;
getans(i + 1, sum + a[i]);//写成i+1避免重复读数
}
}
int main() {
while (scanf("%d", &n) != EOF) {
for (int i = 0;i < n;++i) scanf("%d", &a[i]);
int sum = 0;
cnt = 0;
getans(0, sum);
printf("%d\n", cnt);
}
return 0;
}
八皇后
#include<cstdio>
#include<cmath>
int cnt = 1, P[11];
int res[100][11];
bool hashTable[11] = { false };
void generateP(int index) {
if (index == 9) {
for (int i = 1;i <= 8;++i) {
res[cnt][i] = P[i];
}
++cnt;//得写在for外面
return;
}
for (int i = 1;i <= 8;++i) {
if (hashTable[i] == false) {
bool canput = true;
for (int pre = 1;pre < index;++pre) {
if (abs(pre - index) == abs(P[pre] - i)) {
canput = false;
break;
}
}
if (canput) {
P[index] = i;
hashTable[i] = true;
generateP(index + 1);
hashTable[i] = false;
}
}
}
}
int main() {
generateP(1);
int n;
scanf("%d", &n);
while (n--) {
int m;
scanf("%d", &m);
for (int i = 1;i <= 8;++i) printf("%d", res[m][i]);
printf("\n");
}
return 0;
}
《算法笔记》4.4小节——算法初步->贪心
Codeup
看电视
本题为区间贪心的变体形式,可采用总是先选择左端点最大的区间(或右端点最小的区间)的策略。
#include<cstdio>
#include<algorithm>
using namespace std;
struct TVshow {
int begin, finish;
}s[110];
bool cmp(TVshow a, TVshow b) {
if (a.begin != b.begin) return a.begin > b.begin;
else return a.finish < b.finish;
}
int main() {
int n;
while (scanf("%d", &n) != EOF && n != 0) {
for (int i = 0;i < n;++i) scanf("%d%d", &s[i].begin, &s[i].finish);
sort(s, s + n, cmp);
int ans = 1, lastbegin = s[0].begin;
for (int i = 1;i < n;++i) {
if (s[i].finish <= lastbegin) {
lastbegin = s[i].begin;
++ans;
}
}
printf("%d\n", ans);
}
return 0;
}
出租车费
本题易错点在于容易漏掉余5公里以上的情况,需要注意
#include<cstdio>
int main() {
int n;
while (scanf("%d", &n), n) {
if (n < 4) printf("%d\n", 10);
else if (n <= 8) {
double res = 10 + 2 * (n - 4);
if (res > (int)res) printf("%.1f\n", res);
else printf("%d\n", (int)res);
}
else {
int t = n / 8;
n -= 8 * t;
double res;
if (n >= 5) { //通过计算可得5公里时,平均每公里2.4元,因此若超出t次8后仍有5公里以上,直接计算。
res = 18 * t + 10 + (n - 4) * 2;
}
else {//若t次8之后,只余4公里以内,则无需下车,直接坐超过8公里的2.4元/公里最为划算
res = 2.25 * (t - 1) * 8 + 18 + 2.4 * n;
}
if (res > (int)res) printf("%.1f\n", res);
else printf("%d\n", (int)res);
}
}
return 0;
}
To Fill or Not to Fill
#include<cstdio>
#include<algorithm>
using namespace std;
const int INF = 1 << 30;
struct Station {
double Pi, Di;//油价,距原点距离
}s[510];
bool cmp(Station a, Station b) {
return a.Di < b.Di;
}
int main() {
int n;//中途加油站数,
double Cmax, D, Davg;//邮箱最大储油量,距终点距离,每unit油能行驶的距离
scanf("%lf %lf %lf %d", &Cmax, &D, &Davg, &n);
for (int i = 0;i < n;++i) scanf("%lf %lf", &s[i].Pi, &s[i].Di);
s[n].Di = D;//将终点设置成油价为0的加油站,方便处理
s[n].Pi = 0;
sort(s, s + n, cmp);
if (s[0].Di != 0) printf("The maximum travel distance = 0.00\n");
else {
double ld = Cmax * Davg, price = 0, nowTank = 0;
int i;
for (i = 0;i <= n;) {
int min = -1;//最低油价的加油站编号
double priceMin = INF;//最低油价(不可省略)
for (int j = i + 1;j <= n && s[j].Di - s[i].Di <= ld;++j) {
if (s[j].Pi < priceMin) {
min = j;
priceMin = s[j].Pi;
if (priceMin < s[i].Pi) {
break;
}
}
}
if (min == -1) break;//加满油无法找到加油站
double need = (s[min].Di - s[i].Di) / Davg;//从当前点到min需要的油量
if (s[min].Pi < s[i].Pi) {
price += (need - nowTank) * s[i].Pi;
nowTank = 0;
}
else {
price += (Cmax - nowTank) * s[i].Pi;//加满
nowTank = Cmax - need;
}
i = min;
}
if (i == n) printf("%.2f\n", price);//能到达终点
else printf("The maximum travel distance = %.2f\n", s[i].Di + ld);
}
return 0;
}
Repair the Wall
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 610;
int main() {
int L, n;
int a[maxn];
while (scanf("%d %d", &L, &n) != EOF) {
for (int i = 0;i < n;++i) scanf("%d", &a[i]);
sort(a, a + n);
int sum = 0, cnt = 0;
for (int i = n - 1;i >= 0 && sum < L;--i) {
sum += a[i];
++cnt;
}
if (cnt == n && sum < L) printf("impossible\n");
else printf("%d\n", cnt);
}
return 0;
}
FatMouse’s Trade
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1010;
struct cat {
double f, j, p;//favorite food、JavaBean、一个f能换多少个j
}c[maxn];
bool cmp(cat a, cat b) {
return a.p > b.p;
}
int main() {
double m;
int n;
while (scanf("%lf %d", &m, &n) != EOF && m != -1, n != -1) {
for (int i = 0;i < n;++i) {
scanf("%lf %lf", &c[i].j, &c[i].f);
c[i].p = c[i].j / c[i].f;
}
sort(c, c + n, cmp);
double sum = 0;
for (int i = 0;i < n && m>0;++i) {
if (c[i].f <= m) {
sum += c[i].j;
m -= c[i].f;
}
else {
sum += c[i].p * m;
break;
}
}
printf("%.3f\n", sum);
}
return 0;
}
迷瘴
这道题不难,但是算浓度和输出部分修改了很久,属实不应该。
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 110;
int main() {
int m;
while (scanf("%d", &m) != EOF) {
while (m--) {
int n, v, w;
double poison[maxn];
scanf("%d %d %d", &n, &v, &w);
for (int i = 0;i < n;++i) scanf("%lf", &poison[i]);
sort(poison, poison + n);
int V = 0;
double sum = 0;
for (int i = 0;i < n;++i) {
if ((sum + poison[i]) / (V / v + 1) <= w) {
sum += poison[i];
V += v;
}
else break;
}
if (V == 0) printf("0 0.00\n");
else printf("%d %.2f\n", V, round(sum / (V / v)) / 100);
}
}
return 0;
}
找零钱
#include<cstdio>
const int money[5] = { 50,20,10,5,1 };
int main() {
int n;
while (scanf("%d", &n) != EOF) {
int sum = 0, a[5] = { 0 };
while (sum != n) {
for (int i = 0;i < 5;++i) {
if (sum + money[i] <= n) {
sum += money[i];
++a[i];
break;
}
}
}
bool first = true;
for (int i = 0;i < 5;++i) {
if (a[i]) {
if (first == false) printf("+");
printf("%d*%d", money[i], a[i]);
first = false;
}
}
printf("\n");
}
return 0;
}
配套实战指南
PAT B1023 组个最小数
#include<cstdio>
int main() {
int a[10] = { 0 };
for (int i = 0;i < 10;++i) scanf("%d", &a[i]);
for (int i = 1;i < 10;++i) {
if (a[i] > 0) {
printf("%d", i);
--a[i];
break;
}
}
for (int i = 0;i < 10;++i) {
if (a[i] > 0) {
for (int j = 0;j < a[i];++j) {
printf("%d", i);
}
}
}
return 0;
}
PAT B1020 月饼
本题的易错点关键在于库存量为正数即可以为小数,因此月饼的库存以及单价都应定义为double型,为了方便还需将需求量D定义成double型
#include<cstdio>
#include<algorithm>
using namespace std;
struct Mooncake {
double stock;
double price;
}m[1010];
bool cmp(Mooncake a, Mooncake b) {
return a.price > b.price;
}
int main() {
int n;
double d;
scanf("%d %lf", &n, &d);
for (int i = 0;i < n;++i) scanf("%lf", &m[i].stock);
for (int i = 0;i < n;++i) {
double temp;
scanf("%lf", &temp);
m[i].price = temp / m[i].stock;
}
sort(m, m + n, cmp);
double money;
for (int i = 0;i < n;++i) {
if (d > m[i].stock) {
d -= m[i].stock;
money += m[i].price * m[i].stock;
}
else {
money += m[i].price * d;
d = 0;
break;
}
}
printf("%.2f\n", money);
return 0;
}
PAT A1033 To Fill or Not to Fill
这是一道难题,解题的关键有
①首先在于将终点视为一个单位油价0元离起点距离D的加油站,这样经过排序后循环到终点时即可将其当做一个普通加油站处理,这样做的好处是规避了单用if语句判断是否到达终点
②分析出所有的情况,建议在草稿纸上画图分析,经分析其实可得当前油量不可能超过need——若前一步只加够去较低加油站的油,到达后油量为0,显然小于need,若前一步加满油则说明当前点为满油箱距离内费用最低的点,若能发现更低则说明范围超过满油箱距离,因此亦小于need。
③关于nowTank的值,在走出一步之前,算好到达下一站时的油箱剩余值也是这题一个思考点
#include<cstdio>
#include<algorithm>
using namespace std;
const int INF = 1 << 30;
struct Station {
double Pi, Di;//油价,距原点距离
}s[510];
bool cmp(Station a, Station b) {
return a.Di < b.Di;
}
int main() {
int n;//中途加油站数,
double Cmax, D, Davg;//邮箱最大储油量,距终点距离,每unit油能行驶的距离
scanf("%lf %lf %lf %d", &Cmax, &D, &Davg, &n);
for (int i = 0;i < n;++i) scanf("%lf %lf", &s[i].Pi, &s[i].Di);
s[n].Di = D;//将终点设置成油价为0的加油站,方便处理
s[n].Pi = 0;
sort(s, s + n, cmp);
if (s[0].Di != 0) printf("The maximum travel distance = 0.00\n");
else {
double ld = Cmax * Davg, price = 0, nowTank = 0;
int i;
for (i = 0;i <= n;) {
int min = -1;//最低油价的加油站编号
double priceMin = INF;//最低油价(不可省略)
for (int j = i + 1;j <= n && s[j].Di - s[i].Di <= ld;++j) {
if (s[j].Pi < priceMin) {
min = j;
priceMin = s[j].Pi;
if (priceMin < s[i].Pi) {
break;
}
}
}
if (min == -1) break;//加满油无法找到加油站
double need = (s[min].Di - s[i].Di) / Davg;//从当前点到min需要的油量
if (s[min].Pi < s[i].Pi) {
price += (need - nowTank) * s[i].Pi;
nowTank = 0;
}
else {
price += (Cmax - nowTank) * s[i].Pi;//加满
nowTank = Cmax - need;
}
i = min;
}
if (i == n) printf("%.2f\n", price);//能到达终点
else printf("The maximum travel distance = %.2f\n", s[i].Di + ld);
}
return 0;
}
PAT A1037 Magic Coupon
#include<cstdio>
#include<algorithm>
using namespace std;
int main() {
int coupon[100010], pro[100010];
int nc, np;
scanf("%d", &nc);
int ponc = 0, nenc = 0, ponp = 0, ncnp = 0;
for (int i = 0;i < nc;++i) scanf("%d", &coupon[i]);
scanf("%d", &np);
for (int i = 0;i < np;++i) scanf("%d", &pro[i]);
sort(coupon, coupon + nc);
sort(pro, pro + np);
int i = 0, sum = 0;
while (coupon[i] < 0 && pro[i] < 0) {//不能使用 coupon[i]*pro[i]>0,会导致算两次
sum += coupon[i] * pro[i];
++i;
}
while (coupon[nc - 1] > 0 && pro[np - 1] > 0) {
sum += coupon[nc - 1] * pro[np - 1];
nc--;
np--;
}
printf("%d", sum);
return 0;
}
PAT A1067 Sort with Swap(0, i)
最开始写的检查点1,2超时,原因是使用的是数组存取数,每次需要遍历数组查找需要交换的数的位置,最后看了实战指南改成这样,数组pos[i]
存取的是存取i的位置,并且使用left
确定是否交换完全,避免了遍历一遍数组确定是否交换完全,节省了很多时间,另外在整体上定义的变量k用来确定第一个不在正确位置上的数,亦可防止k每次从0开始节省时间。代码未使用swap
函数交换,因为本人认为无需在意p[0]的值,类似于快速排序,最后在0点处补上0即可,省去了交换的时间。
总的来说,题目设计的并不难,但能想到这些降低时间复杂度的策略拿到满分绝对不是一件容易的事。
#include<cstdio>
int main() {
int n, pos[100010], left = 0;
scanf("%d", &n);
for (int i = 0;i < n;++i) {
int a;
scanf("%d", &a);
pos[a] = i;
if (a != i && a != 0) ++left; //易错点:除零以外未在本位上的数
}
int cnt = 0, k = 1, p = pos[0];
while (left > 0) {
if (p == 0) {
while (k < n) {
if (pos[k] != k) break;
++k;
}
p = pos[k];
pos[k] = 0;
++cnt;
}
else {
int temp = pos[p];
pos[p] = p;
p = temp;
++cnt;
--left;
}
}
printf("%d\n", cnt);
return 0;
}
《算法笔记》4.5小节——算法初步->二分
Codeup
找x
#include<cstdio>
int solve(int a[], int n, int b) {
int left = 0, right = n - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (a[mid] == b) return mid;
else if (a[mid] > b) right = mid - 1;
else left = mid + 1;
}
return -1;
}
int main() {
int n, a[210];
while (scanf("%d", &n) != EOF) {
for (int i = 0;i < n;++i) scanf("%d", &a[i]);
int b;
scanf("%d", &b);
int res = solve(a, n, b);
printf("%d\n", res);
}
return 0;
}
打印极值点下标
这题跟二分有什么必然的联系吗 喵喵?
#include<cstdio>
int main() {
int n, a[85];
while (scanf("%d", &n) != EOF) {
while (n--) {
int t;
scanf("%d", &t);
int cnt = 0;
for (int i = 0;i < t;++i) scanf("%d", &a[i]);
if (a[0] != a[1]) {
printf("0");
++cnt;
}
for (int i = 1;i < t - 1;++i) {
if ((a[i] > a[i - 1] && a[i] > a[i + 1]) || (a[i] < a[i - 1] && a[i] < a[i + 1])) {
if (cnt != 0) printf(" ");
printf("%d", i);
++cnt;
}
}
if (a[t - 1] != a[t - 2]) {
if (cnt != 0) printf(" ");
printf("%d", t - 1);
++cnt;
}
if (cnt != 0) printf("\n");
}
}
return 0;
}
查找
#include<cstdio>
#include<algorithm>
using namespace std;
bool judge(int a[], int left, int right, int b) {
int mid;
while (left <= right) {
mid = (left + right) / 2;
if (a[mid] == b) return true;
else if (a[mid] > b) right = mid - 1;
else left = mid + 1;
}
return false;
}
int main() {
int n, a[110];
while (scanf("%d", &n) != EOF) {
for (int i = 0;i < n;++i) scanf("%d", &a[i]);
sort(a, a + n);
int m;
scanf("%d", &m);
while (m--) {
int temp;
scanf("%d", &temp);
bool res = judge(a, 0, n - 1, temp);
if (res == true) printf("YES\n");
else printf("NO\n");
}
}
return 0;
}
习题5-15 二分法求方程的根
题目当前不可用!
它可能被用于未来的比赛、过去的私有比赛,或者管理员由于尚未测试通过等其他原因暂时停止了该题目用于练习。!
配套实战指南
PAT A1085 Perfect Sequence/ B1030 完美数列(二分法)
本题要注意p*a[i]
可能使用int
可能溢出的情况,因此二分法中要使用long long
否则会导致检查点5出错
#include<cstdio>
#include<algorithm>
using namespace std;
int search(int a[], int left, int right, long long x) {
int L = left;
int mid;
while (left < right) {
mid = (left + right) / 2;
if (a[mid] > x) right = mid;
else left = mid + 1;
}
return left - L;
}
int main() {
int n, p, a[100010];
scanf("%d %d", &n, &p);
for (int i = 0;i < n;++i) scanf("%d", &a[i]);
sort(a, a + n);
int max = -1;
for (int i = 0;i < n;++i) {
int res = search(a, i, n, (long long)p * a[i]);//p与序列中的元素均可能达到E9,因此a[i]*p会达到E18,必须使用long long进行强制类型转换。
if (res > max) max = res;
}
printf("%d\n", max);
return 0;
}
PAT A1010 Radix
①19个检查点,改得头皮发麻,题目给出1-9和a~z,我以为最大只有36进制,没想到可以取到很大,因此,right使用int可能会导致越界,因此结果也会,所以都得使用long long
②进制结果不唯一时,输出最小进制,这里跟随算法笔记中的使用改变low、high值来实现
③ 已知数进制转换时不会溢出,而未知数会,因此当未知数转换结果小于0时,即未知数大于已知数。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
//不唯一得找到最小的
//进制转换时可能会溢出
//right可能会越界
long long inf = 9223372036854775807;
int tonum(char c) {
if (c >= '0' && c <= '9') return c - '0';
else return c - 'a' + 10;
}
long long f(char str[], long long radix, long long t) {//t为上界
int len = strlen(str);
long long n = 0;
for (int i = 0;i < len;++i) {
n = n * radix + tonum(str[i]);
if (n<0 || n>t) return -1;
}
return n;
}
long long solve(char str[], long long left, long long right, long long n) {
long long mid;
while (left <= right) {
mid = (left + right) / 2;
if (f(str, mid, n) == n) return mid;
else if (f(str, mid, n) < n && f(str, mid, n) > 0) left = mid + 1;//f小于0则说明溢出
else right = mid - 1;
}
return -1;
}
int findLargestDigit(char str[]) {
int ans = -1, len = strlen(str);
for (int i = 0;i < len;++i) {
if (tonum(str[i]) > ans) ans = tonum(str[i]);
}
return ans + 1;
}
int main() {
char a[11], b[11];
long long n1 = 0;
int tag, radix;
scanf("%s %s %d %d", a, b, &tag, &radix);
if (tag == 2) {
char temp[11];
strcpy(temp, a);
strcpy(a, b);
strcpy(b, temp);
}
n1 = f(a, radix, inf);
long long low = findLargestDigit(b);
long long high = max(low, n1) + 1;
long long res = solve(b, low, high, n1);
if (res == -1) printf("Impossible\n");
else printf("%lld\n", res);
return 0;
}
PAT A1044 Shopping in Mars
本题关键点在于想到通过第一次循环找到最接近m值的操作
#include<cstdio>
int search(int a[], int left, int right, int x) {
int mid, l = left - 1;
while (left < right) {
mid = (left + right) / 2;
if (a[mid] - a[l] >= x) right = mid;
else left = mid + 1;
}
return left;
}
int main() {
int n, m;
int sum[100010] = { 0 };
scanf("%d %d", &n, &m);
for (int i = 1;i <= n;++i) {
int temp;
scanf("%d", &temp);
sum[i] = sum[i - 1] + temp;
}
int nearS = m + 100;
for (int i = 1;i <= n;++i) {//第一次循环找到≥m,最接近m的数nearS
int r = search(sum, i, n, m);
if (nearS > sum[r] - sum[i - 1] && sum[r] - sum[i - 1] >= m) nearS = sum[r] - sum[i - 1];
if (nearS == m) break;
}
for (int i = 1;i <= n;++i) {//第二次循环找出等于nearS的串串并输出
int r = search(sum, i, n, nearS);
if (sum[r] - sum[i - 1] == nearS) printf("%d-%d\n", i, r);
}
return 0;
}
PAT A1048 Find Coins(二分法解法)
可比哈希写法简单多了
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 100010;
int search(int a[], int left, int right, int x) {
int mid, l = left;
while (left <= right) {
mid = (left + right) / 2;
if (a[mid] == x && mid != l) return mid;
else if (a[mid] < x) left = mid + 1;
else right = mid - 1;
}
return -1;
}
int main() {
int n, m;
int a[maxn] = { 0 };
scanf("%d %d", &n, &m);
for (int i = 0;i < n;++i) scanf("%d", &a[i]);
sort(a, a + n);
for (int i = 0;i < n;++i) {
int res = search(a, i, n - 1, m - a[i]);
if (res != -1) {
printf("%d %d\n", a[i], a[res]);
return 0;
}
}
printf("No Solution\n");
return 0;
}
《算法笔记》4.6小节——算法初步->two pointers
Codeup
二路归并排序(mergesort)递归法 [2*+]
看到通过率是0我也就不纠结了
#include<cstdio>
const int maxn = 100010;
void merge(int a[], int l1, int r1, int l2, int r2) {
int i = l1, j = l2;
int temp[maxn], cnt = 0;
while (i <= r1 && j <= r2) {
if (a[i] <= a[j]) temp[cnt++] = a[i++];
else temp[cnt++] = a[j++];
}
while (i <= r1) temp[cnt++] = a[i++];
while (j <= r2) temp[cnt++] = a[j++];
for (int k = 0;k < cnt;++k) a[l1 + k] = temp[k];
}
void mergesort(int a[], int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
mergesort(a, left, mid);
mergesort(a, mid + 1, right);
merge(a, left, mid, mid + 1, right);
}
}
int main() {
int n, a[maxn];
while (scanf("%d", &n) != EOF) {
for (int i = 0;i < n;++i) scanf("%d", &a[i]);
mergesort(a, 0, n - 1);
for (int i = 0;i < n;++i) printf("%d\n", a[i]);
}
return 0;
}
基础排序III:归并排序
尝试非递归写法
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 100010;
void merge(int a[], int l1, int r1, int l2, int r2) {
int i = l1, j = l2;
int temp[maxn], cnt = 0;
while (i <= r1 && j <= r2) {
if (a[i] <= a[j]) temp[cnt++] = a[i++];
else temp[cnt++] = a[j++];
}
while (i <= r1) temp[cnt++] = a[i++];
while (j <= r2) temp[cnt++] = a[j++];
for (int i = 0;i < cnt;++i) a[l1 + i] = temp[i];
}
void mergesort(int a[], int n) {
for (int step = 2;step / 2 <= n;step *= 2) {
for (int i = 0;i < n;i += step) {
int mid = i + step / 2 - 1;
if (mid + 1 < n) {
merge(a, i, mid, mid + 1, min(i + step - 1, n - 1));
}
}
}
}
int main() {
int n, m;
scanf("%d", &n);
while (n--) {
scanf("%d", &m);
int a[maxn];
for (int i = 0;i < m;++i) scanf("%d", &a[i]);
mergesort(a, m);
for (int i = 0;i < m;++i) printf("%d\n", a[i]);
}
return 0;
}
快速排序 qsort [2*]
#include<cstdio>
const int maxn=5010;
int Partition(int a[],int left,int right){
int temp=a[left];
while(left<right){
while(left<right&&a[right]>temp) --right;
a[left]=a[right];
while(left<right&&a[left]<=temp) ++left;
a[right]=a[left];
}
a[left]=temp;
return left;
}
void quicksort(int a[],int left,int right){
if(left<right){
int pos=Partition(a,left,right);
quicksort(a,left,pos-1);
quicksort(a,pos+1,right);
}
}
int main(){
int n,a[maxn];
scanf("%d",&n);
for(int i=0;i<n;++i) scanf("%d",&a[i]);
quicksort(a,0,n-1);
for(int i=0;i<n;++i) printf("%d\n",a[i]);
return 0;
}
二分递归快排(Qsort) [2*]
练习随机快排
#include<cstdio>
#include<stdlib.h>
#include<cmath>
#include<time.h>
#include<algorithm>
using namespace std;
const int maxn = 100010;
int randPartition(int a[], int left, int right) {
int p = (rand() % (right - left + 1)) + left;
// int p=round(rand()/RAND_MAX*(right-left)+left);
swap(a[p], a[left]);
int temp = a[left];
while (left < right) {
while (left<right && a[right]>temp) --right;
a[left] = a[right];
while (left < right && a[left] <= temp) ++left;
a[right] = a[left];
}
a[left] = temp;
return left;
}
void randquicksort(int a[], int left, int right) {
if (left < right) {
int pos = randPartition(a, left, right);
randquicksort(a, left, pos - 1);
randquicksort(a, pos + 1, right);
}
}
int main() {
srand((unsigned)time(NULL));
int n, a[maxn];
scanf("%d", &n);
for (int i = 0;i < n;++i) scanf("%d", &a[i]);
randquicksort(a, 0, n - 1);
for (int i = 0;i < n;++i) printf("%d\n", a[i]);
return 0;
}
配套实战指南
PAT A1085 Perfect Sequence/ B1030 完美数列(two point)
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 100010;
int main() {
int n, p, a[maxn];
scanf("%d %d", &n, &p);
for (int i = 0;i < n;++i) scanf("%d", &a[i]);
sort(a, a + n);
int max = -1, left = 0, right = 0;
while (left < n) {
if (right == n) break;
while (a[right] <= (long long)p * a[left] && right != n) ++right;
if (right - left > max) max = right - left;
++left;
}
printf("%d", max);
return 0;
}
PAT A1089 Insert or Merge
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 110;
int a[maxn], b[maxn], c[maxn];//a,b分别存放两次原数组,c存放目标数组
int n;
bool isSame(int a[], int b[]) {//判断两个数组是否相等
for (int i = 0;i < n;++i) {
if (a[i] != b[i]) return false;
}
return true;
}
void Print(int a[]) {//输出数组
for (int i = 0;i < n;++i) {
if (i != 0) printf(" ");
printf("%d", a[i]);
}
printf("\n");
}
bool insertSort() {//对a数组进行插入排序
bool flag = false;
for (int i = 1;i < n;++i) {
if (i != 1 && isSame(a, c)) flag = true;//写在前面,使最终a数组成为执行后一步的结果
int temp = a[i], j = i;
while (j > 0 && a[j - 1] > temp) {
a[j] = a[j - 1];
--j;
}
a[j] = temp;
if (flag) return true;
}
return false;
}
void merge(int a[], int l1, int r1, int l2, int r2) {//排序算法
int i = l1, j = l2;
int temp[maxn], cnt = 0;
while (i <= r1 && j <= r2) {
if (a[i] <= a[j]) temp[cnt++] = a[i++];
else temp[cnt++] = a[j++];
}
while (i <= r1) temp[cnt++] = a[i++];
while (j <= r2) temp[cnt++] = a[j++];
for (int i = 0;i < cnt;++i) a[l1 + i] = temp[i];
}
void mergeSort() {//如果不是插入排序则对b数组进行归并排序
bool flag = false;
for (int step = 2;step / 2 <= n;step *= 2) {
if (step != 2 && isSame(b, c)) flag = true;
for (int i = 0;i < n;i += step) {
int mid = i + step / 2 - 1;
merge(b, i, mid, mid + 1, min(i + step - 1, n - 1));
}
if (flag) {
Print(b);
return;
}
}
}
int main() {
scanf("%d", &n);
for (int i = 0;i < n;++i) {
scanf("%d", &a[i]);
b[i] = a[i];
}
for (int i = 0;i < n;++i) scanf("%d", c + i);
if (insertSort()) {
printf("Insertion Sort\n");
Print(a);
}
else {
printf("Merge Sort\n");
mergeSort();
}
return 0;
}
PAT A1029 Median
#include<cstdio>
const int maxn = 1000010;
const int INF = (1 << 30) - 1;
int s1[maxn], s2[maxn];
int main() {
int n1, n2;
scanf("%d", &n1);
for (int i = 0;i < n1;++i) scanf("%d", &s1[i]);
scanf("%d", &n2);
for (int i = 0;i < n2;++i) scanf("%d", &s2[i]);
int mid = (n1 + n2 - 1) / 2, cnt = 0;
int i = 0, j = 0;
s1[n1] = s2[n2] = INF;//不在循环中特判i,j越界则必须加上这句。
while (cnt < mid) {
while (cnt < mid && s1[i] < s2[j]) {
++cnt;
++i;
}
while (cnt < mid && s2[j] < s1[i]) {
++cnt;
++j;
}
}
printf("%d", s1[i] > s2[j] ? s2[j] : s1[i]);
return 0;
}
PAT A1048 Find Coins(two point解法)
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 100010;
int main() {
int n, m;
int a[maxn];
scanf("%d %d", &n, &m);
for (int i = 0;i < n;++i) scanf("%d", &a[i]);
sort(a, a + n);
int left = 0, right = n - 1;
bool find = false;
while (left < right) {
while (left<right && a[right] + a[left]>m) --right;
if (a[left] + a[right] == m) {
break;
}
++left;
}
if (left != right && a[left] + a[right] == m) printf("%d %d\n", a[left], a[right]);
else printf("No Solution\n");
return 0;
}
《算法笔记》4.7小节——算法初步->其他高效技巧与算法
Codeup
求第k大数
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXN = 1000010;
int a[MAXN];
int randPartition(int a[], int left, int right) {
int p = round(rand() / RAND_MAX * (right - left) + left);
swap(a[left], a[p]);
int temp = a[left];
while (left < right) {
while (left<right && a[right]>temp) --right;
a[left] = a[right];
while (left < right && a[left] <= temp) ++left;
a[right] = a[left];
}
a[left] = temp;
return left;
}
int randSelect(int a[], int left, int right, int k) {
if (left == right) return a[left];
int p = randPartition(a, left, right);
int m = p - left + 1;
if (k == m) return a[p];
if (k < m) return randSelect(a, left, p - 1, k);
else return randSelect(a, p + 1, right, k - m);
}
int main() {
srand((unsigned)time(NULL));
int n, k;
scanf("%d %d", &n, &k);
for (int i = 0;i < n;++i) scanf("%d", &a[i]);
int res = randSelect(a, 0, n - 1, n - k + 1);
printf("%d", res);
return 0;
}
配套实战指南
PAT A1093 Count PAT’s/1040 有几个PAT
最开始写了一个果不其然就超时了,看到书上的思路感觉豁然开朗,对于每一个A来说,能构成的PAT数等于A左边的P的个数乘以A右边T的个数,最后将所有A算出的数字进行加和即可。
#include<cstdio>
#include<cstring>
const int MAXN = 100010;
const int MOD = 1000000007;
int main() {
char str[MAXN];
int leftNumP[MAXN] = { 0 };
scanf("%s", str);
int len = strlen(str);
for (int i = 0;i < len;++i) {
if (i > 0) leftNumP[i] = leftNumP[i - 1];
if (str[i] == 'P') ++leftNumP[i];
}
int ans = 0, rightNumT = 0;
for (int i = len - 1;i >= 0;--i) {
if (str[i] == 'T') ++rightNumT;
else if (str[i] == 'A') ans = (rightNumT * leftNumP[i] + ans) % MOD;
}
printf("%d", ans);
return 0;
}
PAT A1101 Quick Sort\PAT B1045 快速排序
由于上一题说本题思路类似,因此想到此法,即申请一个leftlarge
数组记录左边(包括本位)最小的值,申请rightsmall
从右往左遍历数组,当rightsmall=leftlarge[i]
的时候就记录到数组res
中,然后反向输出res
,与书上的方法差不多。
易错点:当主元个数位0时(即不输出时),第二行要输出一个换行
#include<cstdio>
const int MAXN = 100010;
const int INF = (1 << 30) - 1;
int main() {
int n, num[MAXN], leftlarge[MAXN] = { -1 };
scanf("%d", &n);
for (int i = 0;i < n;++i) {
scanf("%d", &num[i]);
if (i > 0) leftlarge[i] = leftlarge[i - 1];
if (num[i] > leftlarge[i]) leftlarge[i] = num[i];
}
int rightsmall = INF, res[MAXN], cnt = 0;
for (int i = n - 1;i >= 0;--i) {
if (num[i] < rightsmall) rightsmall = num[i];
if (rightsmall == leftlarge[i]) res[cnt++] = i;
}
printf("%d\n", cnt);
for (int i = cnt - 1;i >= 0;--i) {
if (i != cnt - 1) printf(" ");
printf("%d", num[res[i]]);
}
printf("\n");
return 0;
}