A
67108864
#include <bits/stdc++.h>
using namespace std;
int main()
{
cout << (256 * 1024 * 1024 / 4);
return 0;
}
B
3181
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <set>
#include <unordered_map>
using namespace std;
int main()
{
unordered_map<int, int> m;
for(int i = 0; i <= 9; ++ i) m[i] = 2021;
int i = 1; //从1开始往后
while(1)
{
int j = i; //copy
while(j)
{
int tmp = j % 10;
j /= 10; //每次去掉最右边的数字
m[tmp] --;
if(m[tmp] < 0) //当前没有该卡片但我要用它
{
cout << i - 1;
return 0;
}
}
i ++;
}
return 0;
}
C
40257
#include <bits/stdc++.h>
using namespace std;
typedef pair<double, double> PDD;
#define x first
#define y second
const int N = 25;
pair<double, double> a[N * N]; //所有点的下标
int idx;
int main()
{
set <PDD> s; //去重 斜率+b
//20行 21列
for(int i = 1; i <= 20; ++ i)
for(int j = 1; j <= 21; ++ j)
{
a[idx].x = i, a[idx].y = j;
idx ++;
}
int ans = 20 + 21; //20行 21列
for(int i = 0; i < idx; ++ i)
{
//i是枚举所有起点
for(int j = 0; j < idx; ++ j)
//j是从该点尝试向所有的点连线
{
if(a[i].x == a[j].x || a[i].y == a[j].y) continue;
double k = 1.0 * (a[j].y - a[i].y) / (a[j].x - a[i].x);
double b = (a[j].x * a[i].y - a[j].y * a[i].x) / (a[j].x - a[i].x);
s.insert({k, b}); //set天然去重 multiset不去重
}
}
ans += s.size();
cout << ans;
return 0;
}
D
2430
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int main()
{
LL n = 2021041820210418;
LL res = 0;
vector<LL> a;
//枚举每一位数字,三个约数相乘
for(LL i = 1; i <= n / i; ++ i)
{
if(n % i == 0)
{
if(i * i != n)
{
a.push_back(i);
a.push_back(n / i);
}
else a.push_back(i);
}
}
LL m = a.size(); //a是所有约数
for(LL i = 0; i < m; ++ i)
for(LL j = 0; j < m; ++ j)
{
LL tmp = a[i] * a[j];
if(n % tmp == 0)
res ++;
}
cout << res;
return 0;
}
E
10266837
#include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef long long LL;
typedef pair<LL, LL> PLL;
const int N = 2030;
LL a[N][N];
LL dist[N];
bool b[N];
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
LL dij()
{
dist[1] = 0;
priority_queue<PLL, vector<PLL>, greater<PLL>> q;
q.push({0, 1}); // val idx
while(q.size())
{
auto it = q.top(); q.pop();
if(b[it.y]) continue;
for(int i = 0; i < N; ++ i)
{
int idx = i, val = a[it.y][i];
if(dist[idx] > dist[it.y] + val)
{
dist[idx] = dist[it.y] + val;
q.push({dist[idx], idx});
}
}
}
return dist[2021];
}
int main()
{
for(int i = 0; i < N; ++ i)
for(int j = 0; j < N; ++ j)
a[i][j] = 1e17;
for(int i = 0; i < N; ++ i) dist[i] = 1e17;
for(int i = 1; i <= 2021; ++ i)
{
for(int j = 1; j <= 21; ++ j)
{
if(i + j >= N) break;
a[i][i + j] = a[i + j][i] = i * (i + j) / gcd(i, i + j);
}
}
LL ans = dij();
cout << ans;
return 0;
}
1. 时间显示
1.1 题目分析
这题挺简单,想清楚一天 24 个小时;一小时 60 分钟;一分钟 60 秒就行了。
1.2 参考源码
#include <iostream>
#include <stdio.h>
using namespace std;
typedef long long LL;
int main()
{
LL x; cin >> x;
x /= 1000;
LL miao, fen, shi;
miao = x; //总秒数
fen = miao / 60; //总分钟数
shi = fen / 60; //总小时数
miao %= 60;
fen %= 60;
shi %= 24;
printf("%02lld:%02lld:%02lld", shi, fen, miao);
return 0;
}
2. 砝码称重
2.1 题目分析
背包问题。令f[i][j]
表示前 i 个总重量为 j 。
对于一个点而言,有三个选择:
- 不加入。
f[i][j] = f[i-1][j]
- 正权。
f[i][j] |= f[i-1][j - wi]
- 负权。
f[i][j] |= f[i-1][j + wi]
2.2 参考源码
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
using namespace std;
const int N = 105, M = 200005;
int D = M / 2; //偏移量,避免出现负下标越界
bool dp[N][M];
int a[N];
int main()
{
int ans = 0;
int n; cin >> n;
for(int i = 1; i <= n; ++ i) cin >> a[i], ans += a[i];
dp[0][0 + D] = true;
for(int i = 1; i <= n; ++ i)
{
for(int j = -ans; j <= ans; ++ j)
{
dp[i][j + D] = dp[i-1][j + D];
if(j - a[i] >= -ans) dp[i][j + D] |= dp[i-1][j - a[i] + D];
if(j + a[i] <= ans) dp[i][j + D] |= dp[i-1][j + a[i] + D];
}
}
int cnt = 0;
for(int i = 1; i <= ans; ++ i)
if(dp[n][i + D]) //1 ~ ans + 偏移量
cnt ++;
cout << cnt;
return 0;
}
3. 杨辉三角形
3.1 题目分析
- 数据范围高达 1 e 9 1e9 1e9 ,暴力一定超时。答案具有二分性。采用二分答案算法。
- 第一次出现必然在左半边。
- 每一行递增、每一斜行从右上到左下递增
斜行从右往左;每个斜行二分答案
3.2 参考源码
#include <iostream>
using namespace std;
typedef long long LL;
int n;
LL C(int a, int b)
{
LL res = 1;
for(int i = a, j = 1; j <= b; i --, j ++)
{
res = res * i / j;
if(res > n) return res;
}
return res;
}
bool check(int k)
{
int l = 2 * k; //l是最右边
int r = max(n, l); //上限是n 有1的情况
while(l < r)
{
int mid = (l + r) >> 1;
if(C(mid, k) >= n) r = mid;
else l = mid + 1;
}
if(C(r, k) != n) return false;
//前面r行
cout << (LL)(1 + r) * r / 2 + k + 1;
return true;
}
int main()
{
cin >> n;
for(int k = 16; ; k --)
if(check(k))
return 0;
return 0;
}
太难了,后续更新