A:空间
256 * 1024 * 1024 / 32 ????!出考场差点没把桌子掀了。
#include <iostream>
using namespace std;
int main() {
cout << 256 * 1024 * 1024 / 4 << endl;
return 0;
}
答案:67108864
B:卡片
#include <iostream>
using namespace std;
int main() {
int a[10];
for (int i = 0; i <= 9; i++) a[i] = 2021;
for (int i = 1; i <= 20210; i++) {
int temp = i;
bool flag = true;
while (temp) {
if (a[temp % 10] == 0) {
flag = false;
break;
}
a[temp % 10]--;
temp /= 10;
}
if (!flag) {
cout << i - 1 << endl;
break;
}
}
return 0;
}
答案:3181
C:直线
直接用set<double, double>
存k,b
就炸了,会少很多,但是这种存所有直线,所以用判断两个数的误差的方法来判断两个数是否相等,学到了。
#include <iostream>
#include <set>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 2e5 + 10;
const double eps = 1e-8;
int cnt = 0;
struct Node {
double k, b;
bool operator< (const Node &W) const {
if (k == W.k) return b < W.b;
return k < W.k;
}
} l[N];
int main() {
for (int x1 = 0; x1 <= 19; x1++) {
for (int y1 = 0; y1 <= 20; y1++) {
for (int x2 = 0; x2 <= 19; x2++) {
for (int y2 = 0; y2 <= 20; y2++) {
if (x1 != x2) {
double k = (double) (y2 - y1) / (x2 - x1);
double b = (double) y1 - k * x1;
l[cnt++] = {k, b};
}
}
}
}
}
sort(l, l + cnt);
int res = 1;
for (int i = 1; i < cnt; i++) {
if (fabs(l[i].k - l[i - 1].k) > eps || fabs(l[i].b - l[i - 1].b) > eps) res++;
}
cout << res + 20 << endl;
return 0;
}
答案:40257
D:货物摆放
首先用计算器算一下,这个数不是一个平方数,所以暴力分解所有约数即可。
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
int main() {
LL n = 2021041820210418;
vector<LL> all;
for (LL i = 1; i <= n / i; i++) {
if (n % i == 0) all.push_back(i);
}
int cnt = all.size();
for (int i = 0; i < cnt; i++) all.push_back(n / all[i]);
int res = 0;
for (auto i1 : all) {
for (auto i2 : all) {
for (auto i3 : all) {
if (i1 * i2 * i3 == n) res++;
}
}
}
cout << res << endl;
return 0;
}
答案:2430
E:路径
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
const int N = 2E6 + 10;
typedef pair<int, int> PII;
int h[3000], e[N], ne[N], w[N], idx;
bool st[3000];
int dist[3000];
void add(int a, int b, int c) {
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
int lcm(int _gcd, int a, int b) {
return _gcd * (a / _gcd) * (b / _gcd);
}
void dijkstra() {
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
priority_queue<PII, vector<PII>, greater<PII>> heap;
heap.push({0, 1});
while (heap.size()) {
auto t = heap.top();
heap.pop();
int ver = t.second;
if (st[ver]) continue;
st[ver] = true;
for (int i = h[ver]; i != -1; i = ne[i]) {
int j = e[i];
if (dist[j] > dist[ver] + w[i]) {
dist[j] = dist[ver] + w[i];
heap.push({dist[j], j});
}
}
}
}
int main() {
memset(h, -1, sizeof h);
for (int a = 1; a <= 2021; a++) {
for (int b = 1; b <= 2021; b++) {
if (abs(a - b) > 21) continue;
int _lcm = lcm(gcd(a, b), a, b);
add(a, b, _lcm), add(b, a, _lcm);
}
}
dijkstra();
cout << dist[2021] << endl;
return 0;
}
答案:10266837
F:时间显示
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
typedef long long LL;
int main() {
LL n;
scanf("%lld", &n);
LL allTs = n / 1000;
LL h = allTs / 3600 % 24;
allTs %= 3600;
LL m = allTs / 60;
allTs %= 60;
printf("%02lld:%02lld:%02lld", h, m, allTs);
return 0;
}
G:砝码称重
就是个01背包问题,考场写爆搜应该得了还不到一半分。
f[i][j]
表示的就是从前i
个物品中选,总重量为k
的集合。
对这里来说,因为有负数,而我们又不能用负坐标,那么就只好加一个偏移量来求了。
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 110, M = 2e5 + 10;
int n;
bool f[N][M];
int w[N];
int main() {
cin >> n;
int m = 0;
for (int i = 1; i <= n; i++) {
cin >> w[i];
m += w[i];
}
f[0][m] = true;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= 2 * m; j++) {
f[i][j] |= f[i - 1][j];
if (j - w[i] >= 0) f[i][j] |= f[i - 1][j - w[i]];
if (j + w[i] <= 2 * m) f[i][j] |= f[i - 1][j + w[i]];
}
}
int res = 0;
for (int i = m + 1; i <= m * 2; i++) {
if (f[n][i]) res++;
}
cout << res << endl;
return 0;
}