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;
}