PAT(乙级)2022年夏季考试 满分 代码不会评论区问,我会回

7-1 又是一道 A+B 简单题细节决定成败

        注意题目给的对应数字的LED灯点亮编号

#include<bits/stdc++.h>
using namespace std;
int main() {
	string s;
	int a = 0, b = 0;
	for (int i = 0; i < 5; ++i) {
		cin >> s;
		if (s == "1011111")
			a = a * 10 + 0;
		else if (s == "0000011")
			a = a * 10 + 1;
		else if (s == "1110110")
			a = a * 10 + 2;
		else if (s == "1110011")
			a = a * 10 + 3;
		else if (s == "0101011")
			a = a * 10 + 4;
		else if (s == "1111001")
			a = a * 10 + 5;
		else if (s == "1111101")
			a = a * 10 + 6;
		else if (s == "1000011")
			a = a * 10 + 7;
		else if (s == "1111111")
			a = a * 10 + 8;
		else if (s == "1111011")
			a = a * 10 + 9;
	}
	for (int i = 0; i < 5; ++i) {
		cin >> s;
		if (s == "1011111")
			b = b * 10 + 0;
		else if (s == "0000011")
			b = b * 10 + 1;
		else if (s == "1110110")
			b = b * 10 + 2;
		else if (s == "1110011")
			b = b * 10 + 3;
		else if (s == "0101011")
			b = b * 10 + 4;
		else if (s == "1111001")
			b = b * 10 + 5;
		else if (s == "1111101")
			b = b * 10 + 6;
		else if (s == "1000011")
			b = b * 10 + 7;
		else if (s == "1111111")
			b = b * 10 + 8;
		else if (s == "1111011")
			b = b * 10 + 9;
	}
	cout << a + b;
	return 0;
}

7-2 健身达人  容器

        直接上容器 map 改成按key非递增排序

#include<bits/stdc++.h>
using namespace std;
int main() {
	int n, id, sp[7];
	map<int, vector<int>, greater<int>> m[8];
	scanf("%d", &n);
	for (int i = 0; i < n; ++i) {
		scanf("%d %d %d %d %d %d %d %d", &id, &sp[0], &sp[1], &sp[2], &sp[3], &sp[4], &sp[5], &sp[6]);
		int c = 0, sum = 0;
		for (int j = 0; j < 7; ++j) {
			if (sp[j]) {
				m[j][sp[j]].push_back(id);
				sum += sp[j];
				++c;
			}
		}
		if (c > 2) m[7][sum].push_back(id);
	}
	for (int i = 0; i < 7; ++i) {
		printf("Star %d\n", i + 1);
		if (m[i].size()) {
			for (int t : m[i].begin()->second)
				printf("%06d\n", t);
		} else printf("NONE\n");
	}
	printf("Star of the week\n");
	for (int t : m[7].begin()->second)
		printf("%06d\n", t);
	return 0;
}

7-3 阶乘方程 这道题看起来很吓人待我给你徐徐道来!

条件: 0≤a<b<c<d    a!d!=b!c!      d 不超过 10^9   所以d最大为1000000000

如果按暴力的传统思路long long 最多存20位 没等乘几次就不够用了

那再想是不是可以用字符串,记住字符串比较耗费时间复杂度,一看题目要求c++ 200 ms 直接放弃字符串  那咋办呢?  用啥数据结构运算呢?

傻孩子,我们可以分解   我们可以变a!d!=b!c!为 d!/c!=b!/a! 是不是可以用除法减少乘法的次数  , 走到了这一步你是不是要直接开乘?  又犯傻了孩子 d如果是1000000 即便是除了c! 结果也早超了long long的20位了?  那咋办呢? 我们发现了吗如果a!d!=b!c!成立起始也就是(b!/a! )/(d!/c!) 为1呗   

例如abcd为0 6 7 10时候 d!/c!=10×9×8  b!/a!=6 ×5×4×3×2×1    按照(b!/a! )/(d!/c!) 为1成立的思想  我们就用b!/a!除以d!/c!看是不是1就ok了呗?  是的 但是你要先求出b!/a! 和 d!/c!然后再相除吗?? 我刚才说了这样会超范围 那咋办? 傻吗? d!/c!不是等于10×9×8吗 且b!/a!=6 ×5×4×3×2×1

我们可以一个数一个数的除 one by one!!!   先定义一个double类型的sum=0.0    在用b!/a!的6除以d!/c!的10为6/10    然后sum*=(6/10)注意转为浮点型      然后用b!/a!的5除以d!/c!的9为5/9  然后sum*=(5/9)    再然后b!/a!的4除以d!/c!的8为4/8   然后sum*=(4/8)        然后发现d!/c!被除完了没数了  但是b!/a!还剩着  我说b!/a!一定剩着,为什么呢?  因为b  a的数码都比 d c 小但是条件还要求

d!/c!=b!/a! 两者相同 那么等式右侧数码小所以要想相等数量就必须多  等式左边数码大要想相等数量就必须少  所以我们先判断b-a是不是大于d-c  用此条件先过一过筛子. 不合法的一定不是不可能相等 合法的不一定相等还需要进一步判断

书接上文     b!/a!还剩着数怎么办?  此时sum=(6/10)×(5/9)×(4/8)  还需要再乘剩下的3 2 1

所以最终sum为(6/10)×(5/9)×(4/8)×3×2×1   判断sum是不是1就行    那这就ok了吗?怎么可能

即使是用double存sum依旧有局限性 因为double不会准确的存储数值 会丢精度 所说如果是等式成立  sum的值应该无线趋近于1 但是不等于1 也就是说sum可能会是0.999699999或者1.000111111111   所以这时候需要判断sum范围 如果在一个可以接受的范围内就是Yes  否则No

那这个范围怎么确定呢? 蒙个数 因为测试数据不会那么细的  我蒙的0.9到1.1  然后对了,没办法太帅了(*^▽^*)

#include<bits/stdc++.h>
using namespace std;
int main() {
	int n, a, b, c, d;
	scanf("%d", &n);
	getchar();
	for (int i = 0; i < n; ++i) {
		scanf("%d %d %d %d", &a, &b, &c, &d);
		getchar();
		if (d - c < b - a) {
			long double sum = 1.0;
			int t1 = d - c, t2 = b - a - d + c;
			while (t1--) {
				sum *= 1.0 * b / d;
				--b;
				--d;
			}
			while (t2--) {
				sum *= 1.0 * b;
				--b;
			}
			if (sum > 0.900000000000 && sum < 1.111111111111) printf("YES\n");
			else printf("NO\n");
		} else printf("NO\n");
	}
	return 0;
}

7-4 今天是周几

注意 测试点5 6   注意处理下面这俩特殊情况

0代表周日 周日的昨天是6即周六

6代表周六 周六的明天为0即周日

#include<bits/stdc++.h>
using namespace std;
string s[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
string ss[3] = {"yesterday", "today", "tomorrow"};
int main() {
	int a[3], b[3] = {1, 0, -1}, y;
	for (int i = 0; i < 3; ++i)
		cin >> a[i];
	for (int i = 0; i < 3; ++i) {
		cin >> y;
		for (int j = 0; j < 3; ++j) {
			int ert = (y == 6 ? (i == 0 ? 0 : 6 + b[i]) : (y == 0 ? (i == 2 ? 6 : 0 + b[i]) : y + b[i]));
			int yit = (a[j] == 6 ? (j == 0 ? 0 : 6 + b[j]) : (a[j] == 0 ? (j == 2 ? 6 : 0 + b[j]) : a[j] + b[j]));
			if (ert == yit) {
				cout << s[yit] << endl;
				cout << ss[j] << endl;
				cout << ss[i] << endl;
				return 0;
			}
		}
	}
	return 0;
}

7-5 LRU缓存 链表存储数据+哈希数组获取是否在队列中和数据与对应链表节点的映射关系

        链表存储数据+哈希数组获取是否在队列中和数据与对应链表节点的映射关系

md说人话好吗? 别这么高级  就是俩map容器 v1 v2   v1存储是不是在缓存中 比如元素为1  如果v1[1]==1 表示在缓存中 v1[1]==0  0表示不在和缓存中   那v2是干嘛的呢?v2呀! 用来获取对应元素的链表地址  我代码是先输入一遍数据 然后 为每个数据创建一个对应节点 把节点指针存储在v2中

比如我们想访问元素1的对应节点  直接从v2里拿节点指针就ok了  v2[1]==node* pointer 用这个pointer就可以操控节点间的顺序了

        我真是太帅了|*´艸`*) 数组的随机存储+链表的增删换位置快捷的优点被我结合了,用来AC这种对时间复杂度有要求的题绰绰有余

#include<bits/stdc++.h>
using namespace std;
struct node {
	int data = -1;
	node *next = NULL, *prior = NULL;
};
int main() {
	int n, m, c = 0;
	scanf("%d %d", &n, &m);
	getchar();
	int a[m];
	unordered_map<int, int> v1;
	unordered_map<int, node*> v2;
	node *h1, *h2;
	h1 = new node;
	h2 = h1;
	for (int i = 0; i < m; ++i) {
		scanf("%d", &a[i]);
		getchar();
		v2[a[i]] = new node;
		v2[a[i]]->data = a[i];
	}
	bool f = 1;
	for (int i = 0; i < m; ++i) {
		if (v1[a[i]] != 1) {
			//不在
//			cout << a[i] << " 不在" << endl;
			if (c >= n) {
				//满出
//				cout << "满出" << h1->next->data << endl;
				int r = h1->next->data;
				printf("%s%d", f ? "" : " ", r);
				f = 0;
				if (r == h2->data) {
//					cout << "是最后一个" << endl;
					h2 = h2->prior;
				}
				h1->next = v2[r]->next;
				if (v2[r]->next != NULL) v2[r]->next->prior = h1;
				v2[r]->next = NULL;
				v2[r]->prior = NULL;
				v1[r] = 0;
				--c;
			}
			h2->next = v2[a[i]];
			v2[a[i]]->prior = h2;
			v2[a[i]]->next = NULL;
			h2 = v2[a[i]];
			v1[a[i]] = 1;
			++c;
//			cout << a[i] << " 入" << endl;
			//入
		} else {
			//在  调位置
//			cout << a[i] << " 在  调位置" << endl;
			if (h2->data != v2[a[i]]->data) {
//				cout << a[i] << " 调位置,不是最后一个" << endl;
				h2->next = v2[a[i]];
				v2[a[i]]->prior->next = v2[a[i]]->next;
				v2[a[i]]->next->prior = v2[a[i]]->prior;
				v2[a[i]]->next = NULL;
				v2[a[i]]->prior = h2;
				h2 = v2[a[i]];
			}
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值