PAT刷题记录-甲级

前言

记录PAT刷题笔记和代码。算法笔记中例题的记录已经放在《算法刷题笔记》文章中了。以下是PAT题库中算法笔记中未出现的题目,这里均为PAT甲级题目。涉及树、图、并查集、堆的题目单独分类了,不在此目录中。

目录

前言

甲级

A1061 Dating

A1062 Talent and Virtue

A1069 The Black Hole of Numbers

A1070 Mooncake

A1073 Scientific Notation

A1074 Reversing Linked List

A1084 Broken Keyboard

A1088 Rational Arithmetic

A1089 Insertion or Merge

A1092 To Buy or Not to Buy

A1093 Count PAT's

A1100 Mars Numbers

A1101 Quick Sort

A1104 Sum of Number Segments

A1105 Spiral Matrix

A1108 Finding Average

A1109 Group Photo

A1110 Complete Binary Tree

A1112 Stucked Keyboard

A1113 Integer Set Partition

A1116 Come on! Let's C

A1117 Eddington Number

A1120 Friend Numbers

A1121 Damn Single

A1124 Raffle for Weibo Followers 

A1125 Chain the Ropes

A1128 N Queens Puzzle

A1129 Recommendation System

A1132 Cut Integer

A1133 Splitting A Linked List

A1136 A Delayed Palindrome

A1137 Final Grading

A1140 Look-and-say Sequence

A1141 PAT Ranking of Institutions

A1144 The Missing Number

A1145 Hashing - Average Search Time 

A1148 Werewolf - Simple Version

A1149 Dangerous Goods Packaging

A1152 Google Recruitment

A1153 Decode Registration Card of PAT


甲级

  • A1061 Dating

字符串扫描匹配。注意字符范围要在合理的范围内,否则会出错,比如对于第一个相同的大写字母,表示星期几,需要在'A'~'G'之间。

#include<cstdio> 
#include<iostream>
#include<string>
#include<cctype>
using namespace std;

string date[7] = {"MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};

int main() {
	string s1, s2, s3, s4;
	cin >> s1 >> s2 >> s3 >> s4; 
	int cnt = 0;
	for(int i = 0; i < s1.length() || i < s2.length(); i ++) {
		if(cnt == 1 && s1[i] == s2[i] && (isdigit(s1[i]) || s1[i] >= 'A' && s1[i] <= 'N')) {
			if(isdigit(s1[i]))
				printf(" %02d:", s1[i] - '0');
			else
				printf(" %02d:", s1[i] - 'A' + 10);
			break;
		}
		if(s1[i] == s2[i] && s1[i] >= 'A' && s1[i] <= 'G') {
			if(cnt == 0)
				printf("%s", date[s1[i] - 'A'].c_str());
			cnt = 1;
		}
	}
	for(int i = 0; i < s3.length() || i < s4.length(); i ++) {
		if(s3[i] == s4[i] && isalpha(s3[i])) {
			printf("%02d", i);
			break;
		}
	}
	return 0;
} 
  • A1062 Talent and Virtue

关键是定义结构体和排序函数。结构体变量中包含id,virtue,talent,还包括一个VT,0表示not rank, 1表示foolman(v>=t),2表示nobleman(Vt),3表示sage(VT)。不满足virtue和talent均不小于L的直接不读入。

排序规则如下:

bool cmp(Man a, Man b) {
	if(a.VT != b.VT)
		return a.VT > b.VT;
	else if(a.virtue + a.talent != b.virtue + b.talent)
		return a.virtue + a.talent > b.virtue + b.talent;
	else if(a.virtue != b.virtue)
		return a.virtue > b.virtue;
	else
		return a.id < b.id;
} 

AC代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn = 100010;
struct Man {
	int id, virtue, talent;
	int VT; // 0:not rank 1 :  v>=h (foolman) 2: Vt(nobleman) 3: VT(sage)
}man[maxn];

bool cmp(Man a, Man b) {
	if(a.VT != b.VT)
		return a.VT > b.VT;
	else if(a.virtue + a.talent != b.virtue + b.talent)
		return a.virtue + a.talent > b.virtue + b.talent;
	else if(a.virtue != b.virtue)
		return a.virtue > b.virtue;
	else
		return a.id < b.id;
} 

int main() {
	int N, L, H, id, v, t;
	scanf("%d %d %d", &N, &L, &H);
	int cnt = 0;
	for(int i = 0; i < N; i ++) {
		scanf("%d %d %d", &id, &v, &t);
		if(v >= L && t >= L) {
			man[cnt].id = id;
			man[cnt].virtue = v;
			man[cnt].talent = t;
			if(v >= H && t >= H) {
				man[cnt].VT = 3;
			}
			else if(v >= H && t < H) {
				man[cnt].VT = 2;
			}
			else if(v < H && t < H && v >= t) {
				man[cnt].VT = 1;
			}
			else man[cnt].VT = 0;
			cnt ++;
		}
	}
	sort(man, man + cnt, cmp);
	printf("%d\n", cnt);
	for(int i = 0; i < cnt; i ++) {
		printf("%08d %d %d\n", man[i].id, man[i].virtue, man[i].talent);
	}
	return 0;
}
  • A1069 The Black Hole of Numbers

用string存放数字。注意输入的数字可能不到4位,需要补充前导0。然后对数字串sort排序,再reverse得到他的倒序,用stoi()转为数字求差,在to_string()转为string,补充前导0至4位,输出等式,然后将差的结果res赋值给num进行下一轮的模拟。

#include<cstdio>
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

int main() {
	string num, num2, res = "";
	cin >> num;
	if(num[0] == num[1] && num[1] == num[2] && num[2] == num[3]) {
		printf("%s - %s = 0000", num.c_str(), num.c_str());
		return 0;
	}
	while(num.length() < 4)
		num.insert(0, "0");
	while(res != "6174") {
		sort(num.begin(), num.end()); 
		num2 = num;
		reverse(num.begin(), num.end()); //larger
		res = to_string(stoi(num) - stoi(num2));
		while(res.length() < 4)
			res.insert(0, "0");
		printf("%s - %s = %s\n", num.c_str(), num2.c_str(), res.c_str());
		num = res;
	}
	return 0;
}
  • A1070 Mooncake

贪心。按单价排序。

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 1010;
struct Mooncake {
	double amount;
	double totalMoney;
	double price;
} mooncake[maxn];

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", &mooncake[i].amount);
	for(int i = 0; i < N; i ++)
		scanf("%lf", &mooncake[i].totalMoney);
	for(int i = 0; i < N; i ++)
		mooncake[i].price = mooncake[i].totalMoney / mooncake[i].amount;
	sort(mooncake, mooncake + N, cmp);		
	double sum = 0.0, totalAmount = 0;
	for(int i = 0; i < N; i ++) {
		if(totalAmount + mooncake[i].amount <= D) {
			totalAmount += mooncake[i].amount;
			sum += mooncake[i].totalMoney;
		}
		else {
			sum += (D - totalAmount) * mooncake[i].price;
			break;
		}
	}
	printf("%.2f", sum);
	return 0;
}
  • A1073 Scientific Notation

这题之前做过一般,这次还不是很熟练,最后好在是一遍过。大体思路有,但细节处理害怕没有考虑全。

思路:首先处理第一个正负号,是负号输出一个‘-’,否则不输出。然后把字符串第一个符号删去。

接下来获取指数E的位置,用substr获得底数部分n和指数部分e,根据指数部分的正负号将情况分为>1和<1两种情况。

小于1需先输出0.,然后不够e的补前导0。

大于1的情况回去指数部分大小,然后从移动小数点的方向考虑,当移动小数点不超过数字长度,则把小数点插到对应位置;否则需要补后面的0,不需要输出小数点。

#include<cstdio>
#include<iostream>
#include<string>
using namespace std;

int main() {
	string num, n, e;
	cin >> num;
	if(num[0] == '-') printf("-");
	num.erase(0, 1);
	int pos = num.find('E');
	n = num.substr(0, pos);
	e = num.substr(pos + 1);
	if(e[0] == '-') {
		printf("0.");
		n.erase(n.find('.'), 1);
		int k = stoi(e.substr(1));
		int i = 0;
		while(i ++ < k - 1)
			n.insert(0, "0");
		printf("%s", n.c_str());
	}
	else {
		int k = stoi(e.substr(1));
		if(k < n.length() - 2) {
			n.erase(n.find('.'), 1);
			n.insert(k + 1, ".");
			printf("%s", n.c_str());
		}
		else {
			n.erase(n.find('.'), 1);
			while(n.length() < k + 1)
				n += "0";
			printf("%s", n.c_str());
		}
	}
	return 0;
}
  • A1074 Reversing Linked List

二刷,这次用的方法思路比第一次更直观,就是先获得一个链表的顺序数组,然后遍历链表将顺序数组中的顺序赋值为order,用于排序。

在实现上述过程中,需要注意一点的是,获得顺序数组时需要先遍历一遍数组获得有效节点个数N(而不是读入时的N,最后一个样例存在无效节点)。

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 100010;
struct Node {
	int addr, data, next;
	int order;
} node[maxn];
int order[maxn];

bool cmp(Node a, Node b) {
	return a.order < b.order;
}

int main() {
	for(int i = 0; i < maxn; i ++) {
		node[i].order = maxn;
	}
	int start, N, K, id;
	scanf("%d %d %d", &start, &N, &K);
	for(int i = 0; i < N; i ++) {
		scanf("%d", &id);
		node[id].addr = id;
		scanf("%d %d", &node[id].data, &node[id].next);
	}
	
	int p = start;
	N = 0;	
	while(p != -1) {
		N ++;
		p = node[p].next;
	} //先统计有效节点数 
	
	p = start;
	int cnt = 0, n = N / K; //获得顺序数组 
	for(int i = 0; i < n; i ++) {
			for(int j = (i + 1) * K - 1; j >= i * K; j --) {
				order[j] = cnt ++;
			}
		}
	for(int i = n * K; i < N; i ++)
		order[i] = cnt ++;
		
	cnt = 0;	
	while(p != -1) { //设置顺序 
		node[p].order = order[cnt ++];
		p = node[p].next;
	}
	sort(node, node + maxn, cmp);
	
	for(int i = 0; i < cnt; i ++) {
		printf("%05d %d", node[i].addr, node[i].data);
		if(i < cnt - 1) printf(" %05d\n", node[i + 1].addr);
		else printf(" -1\n");
	} 
	return 0;
}
  • A1084 Broken Keyboard

hash表的思想。遍历字符串1,将出现的字符(字母大写)的hash值置为1,遍历字符串2,将出现的字符(字母大写)的hash值置0。再次遍历字符串1,按输入顺序判断对应字符hash值是否为1,为1表示没有成功打出,则输出并将hash值置0,遍历置字符串结尾。

#include<cstdio>
#include<iostream>
#include<string>
#include<cctype>
using namespace std;

int hashTable[300] = {0};

int main() {
	string s1, s2;
	cin >> s1 >> s2;
	for(int i = 0; i < s1.length(); i ++) 
		hashTable[toupper(s1[i])] = 1;
	for(int i = 0; i < s2.length(); i ++)
		hashTable[toupper(s2[i])] = 0;
	for(int i = 0; i < s1.length(); i ++) {
		if(hashTable[toupper(s1[i])] == 1) {
			printf("%c", toupper(s1[i]));
			hashTable[toupper(s1[i])] = 0;
		}
	}
	return 0;
}
  • A1088 Rational Arithmetic

分数四则运算。有模板。注意点:分子分母和gcd一般需要用long long存储,因为常常成绩会超过int范围。

#include<cstdio>
#include<algorithm>
using namespace std;

typedef long long LL;
struct Fraction {
	LL up, down;
};

LL gcd(LL a, LL b) {
	if(b == 0) return a;
	else return gcd(b, a % b);
}

//化简 
Fraction reduction(Fraction res) {
	if(res.down < 0) {
		res.up = -res.up;
		res.down = -res.down;
	}
	if(res.up == 0) {
		res.down = 1;
	} 
	else {
		int d = gcd(abs(res.up), abs(res.down));
		res.up /= d;
		res.down /= d;
	}
	return res;
}

Fraction add(Fraction a, Fraction b) {
	Fraction res;
	res.up = a.up * b.down + b.up * a.down;
	res.down = a.down * b.down;
	return reduction(res);
}

Fraction sub(Fraction a, Fraction b) {
	Fraction res;
	res.up = a.up * b.down - b.up * a.down;
	res.down = a.down * b.down;
	return reduction(res);
}

Fraction multi(Fraction a, Fraction b) {
	Fraction res;
	res.up = a.up * b.up;
	res.down = a.down * b.down;
	return reduction(res);
} 

Fraction divide(Fraction a, Fraction b) {
	Fraction res;
	res.up = a.up * b.down;
	res.down = a.down * b.up;
	return reduction(res);
}

void print(Fraction a) {
	a = reduction(a);
	if(a.down == 1) printf("%lld", a.up); //整数
	else if(abs(a.up) > a.down)  { //假分数
		printf("%d %d/%d", a.up / a.down, abs(a.up) % a.down, a.down); 
	}
	else {
		printf("%d/%d", a.up, a.down);
	}
}

int main() {
	Fraction a, b, c;
	scanf("%lld/%lld %lld/%lld", &a.up, &a.down, &b.up, &b.down);
	char op[4] = {'+', '-', '*', '/'};
	for(int i = 0; i < 4; i ++) {
		if(a.up < 0) printf("(");
		print(a);
		if(a.up < 0) printf(")");
		printf(" %c ", op[i]);
		if(b.up < 0) printf("(");
		print(b);
		if(b.up < 0) printf(")");
		printf(" = ");
		switch(i) {
			case 0: c = add(a, b); break;
			case 1: c = sub(a, b); break;
			case 2: c = multi(a, b); break;
			case 3: 
				if(b.up != 0) 
					c = divide(a, b); break;
		}
		if(i == 3 && b.up == 0) {
			printf("Inf");
		}
		else {
			if(c.up < 0) printf("(");
			print(c);
			if(c.up < 0) printf(")");
		}
		printf("\n");
	}
} 
  • A1089 Insertion or Merge

二刷,注意下标是从1开始还是从0开始。每一轮排序前判断当前序列和目标序列是否相同。

其中插入排序的部分的解释:循环遍历i表示排序的轮数。

每一轮(i)排好前i + 1个(i == 1时,排0 ~ 2)。(当i从1开始(数组下标从0开始)时,就是sort(a, a + i + 1); 当i从2开始(数组下标从1开始)时是sort(a + 1, a + i + 1))。

归并排序:用不断*2的step(step从2开始,表示每个块内的元素个数)遍历数组,每一轮排好每个块内的子数组。

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 110;
int origin[maxn], tempOri[maxn], changed[maxn];
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 printArray(int a[]) {
	for(int i = 0; i < N; i ++) {
		if(i > 0) printf(" ");
		printf("%d", a[i]);
	}
}

bool insertionSort() {
	bool flag = false;
	for(int i = 1; i < N; i ++) { //进行N - 1次排序(这里的i和数组下标无关) 
		if(i != 1 && isSame(tempOri, changed)) flag = true;
		sort(tempOri, tempOri + i + 1); //这里的范围是0~(i+1),i = 1: 排0-2
// 		int temp = tempOri[i], j = i;
// 		while(j > 0 && tempOri[j - 1] > temp) {
// 			tempOri[j] = tempOri[j - 1];
// 			j --; 
// 		}
// 		tempOri[j] = temp;
		if(flag == true) return true;
	}
	return false;
}

void mergeSort() {
	bool flag = false;
	for(int step = 2; step / 2 <= N; step *= 2) {
		if(step != 2 && isSame(tempOri, changed)) {
			flag = true;
		}
		for(int i = 0; i < N; i += step) {
			sort(tempOri + i, tempOri + min(i + step , N));
		}
		if(flag == true) {
			printArray(tempOri);
			return;
		}
	}
} 

int main() {
	scanf("%d", &N);
	for(int i = 0; i < N; i ++) {
		scanf("%d", &origin[i]);
		tempOri[i] = origin[i];
	}
	for(int i = 0; i < N; i ++) {
		scanf("%d", &changed[i]);
	}
	if(insertionSort()) {
		printf("Insertion Sort\n");
		printArray(tempOri);
	}
	else {
		printf("Merge Sort\n");
		for(int i = 0; i < N; i ++)
			tempOri[i] = origin[i];
		mergeSort();
	} 
	return 0;
}
  • A1092 To Buy or Not to Buy

二刷。hash。

#include<cstdio>
#include<iostream>
#include<string>
using namespace std;

int hashTable[300] = {0};

int main() {
	string a, b;
	cin >> a >> b;
	for(int i = 0; i < a.length(); i ++) {
		hashTable[a[i]] ++;
	}
	int cnt = 0;
	for(int i = 0; i < b.length(); i ++) {
		if(hashTable[b[i]] > 0) {
			hashTable[b[i]] --;
		}
		else {
			cnt ++;
		}
	}  
	if(cnt > 0) printf("No %d", cnt);
	else printf("Yes %d", a.length() - b.length());
	return 0;
} 
  • A1093 Count PAT's

二刷,但第一眼还是没思路。

思路:对于每一个A,统计左边的P的个数和右边的T的个数。PAT的个数等于左边的P的个数乘以右边的T的个数。关键再用如何统计:从左到右遍历字符串,左边的P的个数至少等于前一项,当s[i] == 'P'时,加1。同理右边的T的个数从右到左遍历,同时遇到'A'将结果加到ans。

#include<cstdio>
#include<iostream>
#include<string>
using namespace std;

const int maxn = 100010;
const int MOD = 1000000007;
int leftNumP[maxn] = {0};

int main() {
	string s;
	cin >> s;
	for(int i = 0; i < s.length(); i ++) {
		if(i > 0)
			leftNumP[i] = leftNumP[i - 1];
		if(s[i] == 'P')
			leftNumP[i] ++;
	}
	int ans = 0, rightNumT = 0;
	for(int i = s.length() - 1; i >= 0; i --) {
		if(s[i] == 'T')
			rightNumT ++;
		else if(s[i] == 'A')
			ans = (ans + leftNumP[i] * rightNumT) % MOD;
	}
	printf("%d", ans);
	return 0;
}
  • A1100 Mars Numbers

二刷,不熟。设置两个映射num2str和str2num。

坑点:str2num时读入需要用getline,因为读入一行含空格的字符串。

打表的方法:先将1~13填好(unitDigit),及13的倍数填好(tenDigit)。再按照先十位(i)后个位(j)的方法遍历填充。s = tenDigit[i] + " " + unitDigit[j]。

#include<cstdio>
#include<iostream>
#include<string>
#include<map>
#include<cctype>
using namespace std;

string unitDigit[13] = {
	"tret",
	"jan", "feb", "mar", "apr", "may", "jun",
	"jly", "aug", "sep", "oct", "nov", "dec"
};

string tenDigit[13] = {
	"tret",
	"tam", "hel", "maa", "huh", "tou", "kes", 
	"hei", "elo", "syy", "lok", "mer", "jou",
};

map<int, string> num2str;
map<string, int> str2num;

void init() {
	for(int i = 0; i < 13; i ++) {
		num2str[i] = unitDigit[i];
		str2num[unitDigit[i]] = i;
		num2str[i * 13] = tenDigit[i];
		str2num[tenDigit[i]] = i * 13;
	}
	for(int i = 1; i < 13; i ++) {
		for(int j = 1; j < 13; j ++) {
			string s = tenDigit[i] + " " + unitDigit[j];
			num2str[i * 13 + j] = s;
			str2num[s] = i * 13 + j;
		}
	}
}

int main() {
	init();
	int n;
	string s;
	cin >> n;
	getchar();
	for(int i = 0; i < n; i ++) {
		getline(cin, s);
		if(isdigit(s[0])) {
			cout << num2str[stoi(s)] << endl;
		}
		else
			cout << str2num[s] << endl;
	}
	return 0;
}
  • A1101 Quick Sort

题意:判断元素是否可能是快排中的主元。只需判断元素是否比左边最大的大,比右边最小的小。因此对于每个元素i需要统计leftMax[i]和rightMin[i]。注意左边最大值和右边最小值的计算过程中不包括元素本身。

坑点:最后需要一个换行。

#include<cstdio>

const int maxn = 100010;
int a[maxn], ans[maxn];
int leftMax[maxn], rightMin[maxn];

int main() {
	int n;
	scanf("%d", &n);
	for(int i = 0; i < n; i ++) {
		scanf("%d", &a[i]);
	}
	leftMax[0] = 0;
	for(int i = 1; i < n; i ++) {
		if(a[i - 1] > leftMax[i - 1]) {
			 leftMax[i] = a[i - 1];
		}
		else
			leftMax[i] = leftMax[i - 1];
	}
	rightMin[n - 1] = 1000000001;
	for(int i = n - 2; i >= 0; i --) {
		if(a[i + 1] < rightMin[i + 1]) {
			rightMin[i] = a[i + 1];
		}
		else
			rightMin[i] = rightMin[i + 1]; 
	}
	
	int cnt = 0;
	for(int i = 0; i < n; i ++) {
		if(a[i] > leftMax[i] && a[i] < rightMin[i]) {
			ans[cnt ++] = a[i];
		}
	}
	printf("%d\n", cnt);
	for(int i = 0; i < cnt; i ++) {
		if(i > 0) printf(" ");
		printf("%d", ans[i]);
	}
	printf("\n");
	return 0;
} 
  • A1104 Sum of Number Segments

找数学规律。数组系数为i * (n - i + 1)。

坑点:数据范围,需要用long double存储。

#include<cstdio>

int main() {
	int n;
	scanf("%d", &n);
	long double a, sum = 0.0;
	for(int i = 1; i <= n; i ++) {
		scanf("%llf", &a);
		sum += a * i * (n - i + 1);
	}
	printf("%.2llf\n", sum);
	return 0;
}
  • A1105 Spiral Matrix

重点:获得N的最相近的两个因子的方法:先取m = (int) ceil(sqrt(1.0 * N)),然后遍历至N% m即可。n = N / m。

坑点:当N == 1时,需特判输出。

思路:将数组排好序。用L, R,U, D四个边界遍历矩阵,每次边界内缩,i ++,j++跳到内一层。第N-1个数特殊处理。

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
 
const int maxn = 10010;
int a[maxn];
int matrix[maxn][maxn];

bool cmp(int a, int b) {
	return a > b;
}

int main() {
	int N;
	scanf("%d", &N);
	for(int i = 0; i < N; i ++)
		scanf("%d", &a[i]);
		
	if(N == 1) {
		printf("%d", a[0]);
		return 0;
	}
	sort(a, a + N, cmp);
	
	int m = (int)ceil(sqrt(1.0 * N));
	while(N % m != 0)
		m ++;
	int n = N / m;
	int L = 1, R = n, U = 1, D = m;
	int i = 1, j = 1, num = 0;
	while(num < N) {
		while(num < N && j < R) {
			matrix[i][j] = a[num ++];
			j ++;
		}
		while(num < N && i < D) {
			matrix[i][j] = a[num ++];
			i ++;
		}
		while(num < N && j > L) {
			matrix[i][j] = a[num ++];
			j --;
		}
		while(num < N && i > U) {
			matrix[i][j] = a[num ++];
			i --;
		}
		U ++, D --, L ++, R --;
		i ++, j ++;
		if(num == N - 1) {
			matrix[i][j] = a[num ++];
		}
	}
	
	for(int i = 1; i <= m; i ++) {
		for(int j = 1; j <= n; j ++) {
			printf("%d", matrix[i][j]);
			if(j < n) printf(" ");
			else printf("\n");
		}
	}
	
	return 0;
}
  • A1108 Finding Average

二刷。发现样例没有两个负号的错误情况。基本上按描述写就能过。

#include<cstdio>
#include<iostream>
#include<string>
#include<cctype>
using namespace std;

bool isLegal(string s) {
	for(int i = 0; i < s.length(); i ++) {
		if(isalpha(s[i])) return false;
		if(s[i] == '.') {
			string ss = s.substr(s.find('.') + 1);
			if(ss.length() > 2) return false;
			if(ss.find('.') != string::npos) return false;
		}
	}
	double d = stod(s);
	if(d < -1000 || d > 1000) return false;
	return true;
}

int main() {
	int n;
	scanf("%d", &n);
	string s;
	double sum = 0.0;
	int cnt = 0;
	for(int i = 0; i < n; i ++) {
		cin >> s;
		if(isLegal(s)) {
			sum += stod(s);
			cnt ++;
		}
		else {
			printf("ERROR: %s is not a legal number\n", s.c_str());
		}
	} 
	if(cnt == 0) printf("The average of 0 numbers is Undefined\n");
	else if(cnt == 1) printf("The average of 1 number is %.2f", sum);
	else printf("The average of %d numbers is %.2f", cnt, sum / cnt);
	return 0;
} 
  • A1109 Group Photo

二刷。没有第一次顺滑。注意K为行数,不是每行人数。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<deque>
using namespace std;

const int maxn = 10010;
struct Student {
	char name[9];
	int height;
} stu[maxn];

bool cmp(Student a, Student b) {
	if(a.height != b.height)
		return a.height > b.height;
	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", stu[i].name, &stu[i].height);
	}
	sort(stu, stu + N, cmp);
	deque<Student> q;
	int rows = N / K;
	int n = N - (K - 1) * rows;
	int num, idx = 0;
	for(int r = 0; r < K; r ++) {
		if(r == 0) num = n;
		else num = rows;
		int cnt = 0;
		while(1) {
			q.push_back(stu[idx ++]);
			if(++ cnt >= num) break;
			q.push_front(stu[idx ++]);
			if(++ cnt >= num) break;
		}
		for(int i = 0; i < q.size(); i ++) {
			printf("%s", q[i].name);
			if(i < q.size() - 1) printf(" ");
			else printf("\n");
		}
		q.clear();
	}
	return 0;
} 
  • A1110 Complete Binary Tree

完全没思路。。憋了半天还是看了题解。

思路:完全二叉树满足:最大下标值 == 最大节点数。递归得到最大下标值。若大于节点数则不是完全二叉树。

  • A1112 Stucked Keyboard

bug找了半天发现是加了个常量(快速debug能力很重要啊。)

思路:遍历字符串,统计连续相同字符个数,如果连续字符数不是k的倍数,则一定不可能是坏的,将hashTable[s[i]](原先初始化为1)置为0。

统计连续相同字符个数的方法:for(j = i; j < s.length() && s[j] == s[i]; j ++); 下一次循环i = j。

注意按照字符发现的顺序输出,不能直接按哈希表中的顺序输出。

输出原串时,第一次遇到坏字符时,将下标i直接后移(k - 1)个(一开始写成样例的的3 - 1了

(╥╯^╰╥))。

#include<cstdio>
#include<iostream>
#include<string>
using namespace std;

int hashTable[256] = {0};
int count[256] = {0};

int main() {
	int k;
	cin >> k;
	string s;
	cin >> s;
	for(int i = 0; i < s.length(); i ++)
		hashTable[s[i]] = 1; 
	int j;
	for(int i = 0; i < s.length(); i = j) {
		for(j = i; j < s.length() && s[j] == s[i]; j ++);
		if((j - i) % k != 0) hashTable[s[i]] = 0;
	}
	for(int i = 0; i < s.length(); i ++) {
		if(hashTable[s[i]] == 1 && count[s[i]] == 0) {
			printf("%c", s[i]);
			count[s[i]] = 1;
		}
	}
	printf("\n");
	for(int i = 0; i < s.length(); i ++) {
		if(hashTable[s[i]] == 1) i += k - 1;
		printf("%c", s[i]);
	}
	return 0;
} 
  • A1113 Integer Set Partition

将整数分为两个集合,要求集合内整数个数差最小,集合内的整数和之差最大。

如果n是奇数,个数差最小为1,n为偶数则为0。和之差最大只需将数组排序,n / 2 给小数组,后 n / 2给大数组即可。

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 100010;
int a[maxn];

int main() {
	int n, sum = 0;
	scanf("%d", &n);
	for(int i = 0; i < n; i ++) {
		scanf("%d", &a[i]);
		sum += a[i];
	}
	sort(a, a + n);
	int s1 = 0;
	for(int i = 0; i < n / 2; i ++) {
		s1 += a[i];
	}
	printf("%d %d", n % 2, sum - s1 - s1);
	return 0;
}

水题:用map记录排名和查询情况,写个判断质数的函数就好了。

#include<cstdio> 
#include<map>
using namespace std;

map<int, int> Rank, checked;

bool isPrime(int x) {
	if(x < 2) return false;
	for(int i = 2; i * i <= x; i ++) 
		if(x % i == 0)
			return false;
	return true;
} 

int main() {
	int n, k, id;
	scanf("%d", &n);
	for(int i = 1; i <= n; i ++) {
		scanf("%d", &id);
		Rank[id] = i;
	}
	scanf("%d", &k);
	for(int i = 0; i < k; i ++) {
		scanf("%d", &id);
		if(Rank[id] == 0) {
			printf("%04d: Are you kidding?\n", id);
		}
		else if(checked[id] != 0) {
			printf("%04d: Checked\n", id);
		}
		else {
			checked[id] = 1;
			if(Rank[id] == 1) {
				printf("%04d: Mystery Award\n", id);
			}
			else if(isPrime(Rank[id])) {
				printf("%04d: Minion\n", id);
			}
			else {
				printf("%04d: Chocolate\n", id);
			}
		}
	}
	return 0;
} 
  • A1117 Eddington Number

二刷。从大到小sort,a[i] <= i时break。

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 100010;
int a[maxn];

bool cmp(int a, int b) {
	return a > b;
}

int main() {
	int n;
	scanf("%d", &n);
	for(int i = 1; i <= n; i ++)
		scanf("%d", &a[i]);
	sort(a + 1, a + n + 1, cmp);
	int i;
	for(i = 1; i <= n; i ++) {
		if(a[i] <= i) break;
	}
	printf("%d", i - 1);
	return 0;
}
  • A1120 Friend Numbers

#include<cstdio>
#include<iostream>
#include<string>
using namespace std;

int hashTable[40] = {0};

int main() {
	int n;
	scanf("%d", &n);
	string num;
	for(int i = 0; i < n; i ++) {
		cin >> num;
		int sum = 0;
		for(int j = 0; j < num.size(); j ++)
			sum += num[j] - '0';
		hashTable[sum] = 1;
	}
	int cnt = 0;
	int friendNum[40];
	for(int i = 0; i < 40; i ++) {
		if(hashTable[i] != 0) {
			friendNum[cnt ++] = i;
		}
	}
	printf("%d\n", cnt);
	for(int i = 0; i < cnt; i ++) {
		if(i > 0) printf(" ");
		printf("%d", friendNum[i]);
	}
	return 0;
}
  • A1121 Damn Single

注:在原集合中查找删除的方法出现了段错误,使用新集合加入单身狗则可以通过。

#include<cstdio>
#include<map>
#include<set>
using namespace std;

map<int, int> couple;

int main() {
	int n, m;
	scanf("%d", &n);
	int u, v;
	for(int i = 0; i < n; i ++) {
		scanf("%d %d", &u, &v);
		couple[u] = v;
		couple[v] = u;
	}
	scanf("%d", &m);
	set<int> party, single;
	for(int i = 0; i < m; i ++) {
		scanf("%d", &u);
		party.insert(u);
	}
	for(auto it : party) {
		if(party.find(couple[it]) == party.end()) {
			single.insert(it);
		}
	}
	printf("%d\n", single.size());
	for(auto it = single.begin(); it != single.end(); it ++) {
		if(it != single.begin()) printf(" ");
		printf("%05d", *it);
	}
	return 0;
}
  • A1124 Raffle for Weibo Followers 

两个点:1、下标从1到m(<=m)2、while() i ++,而不是if() i ++,因为i ++下一个可能还是重复的。

#include<cstdio>
#include<iostream>
#include<string>
#include<map>
using namespace std;

const int maxn = 1010;
string namelist[maxn];
map<string, int> mp;

int main() {
	int m, n, s;
	scanf("%d %d %d", &m, &n, &s);
	for(int i = 1; i <= m; i ++) {
		cin >> namelist[i];
	}
	if(s > m) printf("Keep going...\n");
	for(int i = s; i <= m; i += n) {
		while(mp[namelist[i]] == 1) i ++; 
		printf("%s\n", namelist[i].c_str());
		mp[namelist[i]] = 1;
	}
	return 0;
}
  • A1125 Chain the Ropes

优先队列(最小堆)。

#include<cstdio>
#include<queue>
using namespace std;

int main() {
	int n, s;
	priority_queue<int, vector<int>, greater<int>> q;
	scanf("%d", &n);
	for(int i = 0; i < n; i ++) {
		scanf("%d", &s);
		q.push(s);
	}
	while(q.size() > 1) {
		int s1 = q.top();
		q.pop();
		int s2 = q.top();
		q.pop();
		q.push((s1 + s2) / 2);
	}
	printf("%d", q.top());
	return 0;
}
  • A1128 N Queens Puzzle

题意:判断给定序列是否满足N皇后的解。

解法:判断是否在同一横线上(即seq[i] == seq[j]),再同一横线上则返回false。然后判断两点是否成对角线(即斜率为1)。注意不要用除法,因为整数除法有舍入,直接判断是否坐标差相等即可(abs(seq[j] - seq[i]) == (j - i))。

注意点:数组定义在全局后不需要申请,如果定义成局部变量,需要动态申请空间,否则会出错

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 1010;
int seq[maxn];

bool isSolution(int n) {
	for(int i = 1; i <= n; i ++) {
		for(int j = i + 1; j <= n; j ++) {
			if(seq[i] == seq[j]) {
				return false;
			}
			if(abs(seq[j] - seq[i]) == (j - i)) {
				return false;
			}
		}
	}
	return true;
}

int main() {
	int k, n;
	scanf("%d", &k);
	for(int i = 0; i < k; i ++) {
		scanf("%d", &n);
		for(int j = 1; j <= n; j ++)
			scanf("%d", &seq[j]);
		if(isSolution(n)) printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}

  • A1129 Recommendation System

题意:根据历史访问信息,实时推荐前k个item。

解法:可以map按值排序,只需将将map中元素存到vector<pair<int, int>>数组中排序即可,但是两个测试点超时。

因此换一种方法,用可以自动按键排序的set。设置Item结构体,其中需要写一个operator<函数才能放入set,排序规则按题目要求先cnt再id。

将读入item的存放到items数组,用times数组记录item出现次数。然后第一个item之后每次输入item时,都需要推荐(实时性),输出此时至多前k个item。然后在set中找到当前的item并删除,因为它的cnt需要被更新(加1),在times数组更新cnt后,构造一个新的Item放入set。如此继续下去。

注意点:give to sth. 在某事上花时间。

#include<cstdio>
#include<set>
#include<map>
#include<algorithm>
using namespace std;

struct Item {
	int id, cnt;
	Item(int _id, int _cnt) : id(_id), cnt(_cnt) {}
	bool operator < (const Item& b) const {
		if(cnt != b.cnt) return cnt > b.cnt;
		else return id < b.id;
	}
};

const int maxn = 50010;
int items[maxn], times[maxn];

int main() {
	int n, k, id;
	set<Item> s;
	scanf("%d %d", &n, &k);
	for(int i = 0; i < n; i ++) 
		scanf("%d", &items[i]);
	s.insert(Item(items[0], 1));
	times[items[0]] = 1;
	for(int i = 1; i < n; i ++) {
		printf("%d:", items[i]);
		int j = 0;
		for(auto it = s.begin(); it != s.end() && j < k; it ++, j ++) {
			printf(" %d", it->id);
		}
		if(s.find(Item(items[i], times[items[i]])) != s.end()) {
			s.erase(Item(items[i], times[items[i]]));
		}
		times[items[i]] ++;
		s.insert(Item(items[i], times[items[i]]));
		printf("\n");
	}
	return 0;
}
  • A1132 Cut Integer

题意:判断一个数字能不能被它分成前后两段的数字的乘积整除。

分析:直接按要求计算,一开始以为会溢出,但发现是浮点错误。原因以下:

 因此想到可能是后半段的数组可能全是0,出现了除0错误。

#include<cstdio>
#include<iostream>
#include<string>
using namespace std;

int main() {
	int n;
	scanf("%d", &n);
	string num;
	for(int i = 0; i < n; i ++) {
		cin >> num;
		string left = num.substr(0, num.size() / 2);
		string right = num.substr(num.size() / 2);
		int x = stoi(num);
		int l = stoi(left);
		int r = stoi(right);
		if(r == 0) printf("No\n");
		else if(x % (l * r) == 0) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}
  • A1133 Splitting A Linked List

题意:链表排序。

解法:结构体Node中设置变量order表示链表的顺序。设置变量flag:flag == 0,表示小于0;flag == 1,表示小于等于K,flag == 2表示其它元素。初始化节点数组的flag和order都为maxn(其实只有将flag置为maxn就行了),让不在链表中的元素排到数组最后。

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 100010;
struct Node {
	int addr;
	int data;
	int next;
	int order;
	int flag; //0: less0, 1: lessK, 2: moreK
} node[maxn];

bool cmp(Node a, Node b) {
	if(a.flag != b.flag) return a.flag < b.flag;
	else return a.order < b.order;
}

void init() {
	for(int i = 0; i < maxn; i ++) {
		node[i].flag = maxn;
//		node[i].order = maxn;
	}	
}

int main() {
	init();
	int st, n, k, addr;
	scanf("%d %d %d", &st, &n, &k); 
	for(int i = 0; i < n; i ++) {
		scanf("%d", &addr);
		node[addr].addr = addr;
		scanf("%d %d", &node[addr].data, &node[addr].next);
	}
	int p = st, cnt = 0;
	while(p != -1) {
		node[p].order = cnt ++;
		if(node[p].data < 0) node[p].flag = 0;
		else if(node[p].data <= k) node[p].flag = 1;
		else node[p].flag = 2;
		p = node[p].next;
	}
	sort(node, node + maxn, cmp);
	for(int i = 0; i < cnt; i ++) {
		printf("%05d %d ", node[i].addr, node[i].data);
		if(i < cnt - 1) printf("%05d\n", node[i + 1].addr); 
		else printf("-1\n");
	}
	return 0;
} 
  • A1136 A Delayed Palindrome

题意:判断是否是延迟的回文数。

分析:一开始直接使用to_string()和stoi()完成加法,发现最后一个样例运行时错误。题目说不超过1000位,说明可能是大整数(应该就是最后一个测试用例)。因此实现大整数加法。通过。

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

bool isPalindromic(string num) {
	int len = num.size(); 
	for(int i = 0; i < len / 2; i ++)
		if(num[i] != num[len - i - 1]) 
			return false;
	return true;
}

string add(string a, string b) {
	string c;
	reverse(a.begin(), a.end());
	reverse(b.begin(), b.end());
	int carry = 0;
	for(int i = 0; i < a.length() || i < b.length(); i ++) {
		int temp = a[i] - '0' + b[i] - '0' + carry;
		c.insert(0, to_string(temp % 10));
		carry = temp / 10;
	}
	if(carry != 0) c.insert(0, to_string(carry));
	return c;
}

int main() {
	string a;
	cin >> a;
	int cnt = 0;
	while(cnt < 10) {
		if(isPalindromic(a)) {
			printf("%s is a palindromic number.\n", a.c_str());
			break;
		} 
		cnt ++;
		string b = a;
		reverse(b.begin(), b.end());
		string c = add(a, b);
		printf("%s + %s = %s\n", a.c_str(), b.c_str(), c.c_str());
		a = c;
	}
	if(cnt == 10) 
		printf("Not found in 10 iterations.\n");
	return 0;
}

  • A1137 Final Grading

题意:结构体排序,分多次输入不同成员变量。

解法:用map<string, int> idx建立id的唯一的整数映射。设置一个ans数组保存符合条件的元素,然后排序。

注意点:rounded up, 对x四舍五入的方法:int(x + 0.5);

#include<iostream>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;

struct node {
	string id;
	int Gp, Gm, Gf, G;
};
map<string, int> idx;

bool cmp(node a, node b) {
	return a.G != b.G ? a.G > b.G : a.id < b.id;
}

int main() {
	int p, m, n, score, cnt = 1;
	scanf("%d %d %d", &p, &m, &n);
	vector<node> v, ans;
	string id;
	for(int i = 0; i < p; i ++) {
		cin >> id >> score;
		if(score >= 200) {
			v.push_back(node{id, score, -1, -1, 0});
			idx[id] = cnt ++;
		}
	}
	for(int i = 0; i < m; i ++) {
		cin >> id >> score;
		if(idx[id] != 0) {
			v[idx[id] - 1].Gm = score;
		}
	}
	for(int i = 0; i < n; i ++) {
		cin >> id >> score;
		if(idx[id] != 0) {
			int temp = idx[id] - 1;
			v[temp].Gf = v[temp].G = score;
			if(v[temp].Gm > v[temp].Gf) 
				v[temp].G = int(v[temp].Gm * 0.4 + v[temp].Gf * 0.6 + 0.5);
		}
	}
	for(int i = 0; i < v.size(); i ++)
		if(v[i].G >= 60) ans.push_back(v[i]);
	sort(ans.begin(), ans.end(), cmp);
	for(int i = 0; i < ans.size(); i ++) 
		printf("%s %d %d %d %d\n", ans[i].id.c_str(), ans[i].Gp, ans[i].Gm, ans[i].Gf, ans[i].G);
	return 0;
} 

  • A1140 Look-and-say Sequence

题意:看说序列,用下一个序列描述上一个序列,一个元素跟着它的个数。

解法:关键是统计连续字符的个数: for(j = i; s[j] == s[i]; j ++);

#include<iostream> 
using namespace std;

string getNext(string s) {
	string ans;
	int j; 
	for(int i = 0; i < s.length(); i = j) {
		for(j = i; s[j] == s[i]; j ++);
		ans += s[i]; 
		ans += to_string(j - i);
	}
	return ans;
}

int main() {
	string d;
	int n;
	cin >> d >> n;
	for(int i = 0; i < n - 1; i ++) {
		d = getNext(d);
	}
	printf("%s", d.c_str());
	return 0;
}

  • A1141 PAT Ranking of Institutions

题意:排序题。

解法:用map将string映射成int得到整数id。

#include<cstdio>
#include<cctype>
#include<iostream>
#include<map>
#include<algorithm>
using namespace std;

const int maxn = 100010;
struct School {
	string id;
	int Bscore, Ascore, Tscore;
	int score;
	int rank;
	int stuNum;
} school[maxn];
map<string, int> idx;

string toSmall(string name) {
	for(int i = 0; i < name.size(); i ++)
		name[i] = tolower(name[i]);
	return name;
}

bool cmp(School a, School b) {
	if(a.score != b.score) return a.score > b.score;
	else if(a.stuNum != b.stuNum) return a.stuNum < b.stuNum;
	else return a.id < b.id;
}

int main() {
	int n, score, cnt = 1;
	string id, name;
	scanf("%d", &n);
	for(int i = 1; i <= n; i ++) {
		cin >> id >> score >> name;
		name = toSmall(name); 
		if(idx[name] == 0) idx[name] = cnt ++;
		school[idx[name]].id = name;
		if(id[0] == 'B') school[idx[name]].Bscore += score;
		else if(id[0] == 'A') school[idx[name]].Ascore += score;
		else if(id[0] == 'T') school[idx[name]].Tscore += score; 
		school[idx[name]].stuNum ++;
	}
	for(int i = 1; i <= cnt - 1; i ++) 
		school[i].score = (int)(school[i].Bscore / 1.5 + school[i].Ascore + school[i].Tscore * 1.5);
	sort(school + 1, school + cnt, cmp);
	school[1].rank = 1;
	for(int i = 2; i <= cnt - 1; i ++) {
		if(school[i].score == school[i - 1].score)
			school[i].rank = school[i - 1].rank;
		else if(school[i].score < school[i - 1].score)
			school[i].rank = i;
	}
	printf("%d\n", cnt - 1);
	for(int i = 1; i <= cnt - 1; i ++) 
		printf("%d %s %d %d\n", school[i].rank, school[i].id.c_str(), school[i].score, school[i].stuNum);
	return 0;
}
  • A1144 The Missing Number

题意:找到最小的没出现的整数。

解法:读入的数装入set,然后从1开始遍历查找。

注意点:while的括号里面的语句会先于循环主体执行。

#include<cstdio>
#include<set>
using namespace std;
 
int main() {
	int n, num;
	scanf("%d", &n);
	set<int> s;
	for(int i = 0; i < n; i ++) {
		scanf("%d", &num);
		s.insert(num);
	}
	int j = 1;
	while(true) {
		if(s.find(j) == s.end()) {
			printf("%d", j);
			break;
		}
		j ++;
	}
	return 0;
} 
  • A1145 Hashing - Average Search Time

题意:hash和冲突的解决。读了几遍题目才明白意思。所谓比较次数,就是探测的次数。

解法:hash表+平方探测解决冲突。统计查找次数还是用二次探测法,每次探测算一次比较 ,注意当找到元素(hashTable[key] == x)或元素不存在(hashTable[key] == 0)时结束探测。

#include<cstdio>

const int maxn = 10001;
int hashTable[maxn] = {0};

bool isPrime(int n) {
	if(n < 2) return false;
	for(int i = 2; i * i <= n; i ++)
		if(n % i == 0) return false;
	return true;
}

int main() {
	int MSize, n, m;
	scanf("%d %d %d", &MSize, &n, &m);
	while(isPrime(MSize) == false) MSize ++;
	int x;
	for(int i = 0; i < n; i ++) {
		scanf("%d", &x);
		int key = x % MSize;
		if(hashTable[key] == 0) {
			hashTable[key] = x;
		}
		else {
			int step;
			for(step = 1; step < MSize; step ++) {
				key = (x + step * step) % MSize; 
				if(hashTable[key] == 0) {
					hashTable[key] = x;
					break;
				}
			}
			if(step >= MSize) {
				printf("%d cannot be inserted.\n", x);
			}
		}
	}
	int cnt = 0;
	for(int i = 0; i < m; i ++) {
		scanf("%d", &x);
		for(int step = 0; step <= MSize; step ++) {
			cnt ++;
			int key = (x + step * step) % MSize;
			if(hashTable[key] == x || hashTable[key] == 0) break;
		}
	}
	printf("%.1f", cnt * 1.0 / m);
	return 0;
}

  • A1148 Werewolf - Simple Version

MARK.

题意:狼人杀。有两人说谎,其中有一个是狼人。

解法:将每个人的说法保存到数组v中。设一个数组表示真实情况,1是好人,-1是狼人。枚举是狼人的两个人的所有情况。然后遍历每个人的说法v[k],如果这个人的说法和真实情况不符,即v[k] * a[abs(v[k])]为负数,则将这个人k加入说谎数组。最后如果说谎人数为2,且说谎的一个是好人一个时狼人则满足题目要求。

#include<iostream>
#include<vector>
using namespace std;

int main() {
	int n;
	cin >> n;
	vector<int> v(n + 1);
	for(int i = 1; i <= n; i ++)
		cin >> v[i];
	for(int i = 1; i <= n; i ++) {
		for(int j = i + 1; j <= n; j ++) {
			vector<int> lie, a(n + 1, 1); //说谎,狼人-1/好人1
			a[i] = a[j] = -1;
			for(int k = 1; k <= n; k ++) 
				if(v[k] * a[abs(v[k])] < 0) lie.push_back(k);
			if(lie.size() == 2 && a[lie[0]] + a[lie[1]] == 0) {
				cout << i << " " << j;
				return 0;
			}
		}
	}
	cout << "No Solution";
	return 0;
} 

  • A1149 Dangerous Goods Packaging

题意:集合中出现了某物品不相容的物品则输出No。

解法:注意可能有一个物品有多个不相容物品,因此简单的使用map<int, int>不可行。因此使用map<int, set<int>>来记录不相容物品。对于每个测试集合的物品,判断其每个不相容物品是否出现在该集合中,如果出现则输出No,否则输出Yes。

#include<cstdio>
#include<map>
#include<set>
using namespace std;

map<int, set<int>> mp;

int main() {
	int n, m, k, a, b;
	scanf("%d %d", &n, &m);
	for(int i = 0; i < n; i ++) {
		scanf("%d %d", &a, &b);
		mp[a].insert(b);
		mp[b].insert(a);
	}
	for(int i = 0; i < m; i ++) {
		scanf("%d", &k);
		set<int> s; 
		for(int j = 0; j < k; j ++) {
			scanf("%d", &a);
			s.insert(a);
		}
		bool flag = false;
		for(auto it1 : s) {
			for(auto it2 : mp[it1]) {
				if(s.find(it2) != s.end()) {
					flag = true;
					break;
				}
			}
		}
		if(flag) printf("No\n");
		else printf("Yes\n");
	}
	return 0;
}

  • A1152 Google Recruitment

题意:找到数字串最左边的长度为K的质数。

解法:从左到右遍历,取出长度为K的子串,判断是否是质数。注意边界条件是i + K <= L,对应长度为L的子串。

#include<iostream>
using namespace std;

bool isPrime(int x) {
	if(x < 2) return false;
	for(int i = 2; i * i <= x; i ++)
		if(x % i == 0) return false;
	return true; 
}

int main() {
	int L, K;
	string num;
	cin >> L >> K >> num;
	int i;
	for(i = 0; i + K <= L; i ++)
		if(isPrime(stoi(num.substr(i, K)))) {
			cout << num.substr(i, K) << endl;
			break;
		}
	if(i + K > L) cout << "404" << endl;
	return 0;
}

  • A1153 Decode Registration Card of PAT

关键点:unordered_map效率高于map。map按值排序。

#include<cstdio>
#include<iostream>
#include<unordered_map>
#include<algorithm>
#include<vector>
using namespace std;

const int maxn = 10010;
struct Student {
	string id;
	int score;
} stu[maxn];

bool cmp(Student a, Student b) {
	if(a.score != b.score) return a.score > b.score;
	else return a.id < b.id;
}

bool cmpMap(pair<string, int> a, pair<string, int> b) {
	return a.second != b.second ? a.second > b.second : a.first < b.first;
}

int main() {
	int  n, m;
	scanf("%d %d", &n, &m);
	for(int i = 0; i < n; i ++) {
		cin >> stu[i].id >> stu[i].score;
	}
	sort(stu, stu + n, cmp);
	int type;
	string cmd;
	for(int k = 0; k < m; k ++) {
		cin >> type >> cmd;
		printf("Case %d: %d %s\n", k + 1, type, cmd.c_str());
		int cnt = 0, sum = 0;
		if(type == 1) {
			bool flag = false;
			for(int i = 0; i < n; i ++) {
				if(stu[i].id[0] == cmd[0]) {
					flag = true;
					printf("%s %d\n", stu[i].id.c_str(), stu[i].score);
				}
			}
			if(flag == false) printf("NA\n");
		}
		else if(type == 2) {
			for(int i = 0; i < n; i ++) {
				if(stu[i].id.substr(1, 3) == cmd) {
					cnt ++;
					sum += stu[i].score;
				}
			}
			if(cnt != 0) printf("%d %d\n", cnt, sum);
			else printf("NA\n");
		}
		else if(type == 3) {
			unordered_map<string, int> mp;
			for(int i = 0; i < n; i ++) {
				if(stu[i].id.substr(4, 6) == cmd) {
					mp[stu[i].id.substr(1, 3)] ++;
				}
			}
			vector<pair<string, int>> v(mp.begin(), mp.end());
			sort(v.begin(), v.end(), cmpMap);
			for(int i = 0; i < v.size(); i ++)
				printf("%s %d\n", v[i].first.c_str(), v[i].second);
			if(v.size() == 0) printf("NA\n"); 
		}
	}
	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值