模拟赛SXJ202507250900比赛记录&题解
题目请看
T1
一点点贪心,因为包包每天都要吃饺子,所以问题可以转化为看是之前\(买饺子的钱+存储的钱\)与\(现在购买饺子的钱\),把它们进行比较,就能知道怎样更划算了;
贴一下代码
#include <bits/stdc++.h>
using namespace std;
#define fre(c) freopen(c".in","r",stdin);freopen(c".out","w",stdout);
#define ll long long
#define endl "\n"
#define ios ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define cst const
cst ll N = 1e5 + 5;
ll n, c, a[N], ans, daymi;
ll read() {
char c;
ll sum = 0;
int f = 1;
c = getchar();
while (!isdigit(c)) {
if (c == '-')
f *= -1;
c = getchar();
}
while (isdigit(c)) {
sum = sum * 10 + (c - '0');
c = getchar();
}
return sum * f;
}
int main() {
ios
// fre("1")
fre("dumpling")
n = read();
c = read();
for (ll i = 1; i <= n; i ++) {
a[i] = read();
}
daymi = a[1];
for (ll i = 1; i <= n; i ++) {
daymi = min(daymi, a[i] - c * i);
ans += daymi + c * i;
}
cout << ans;
return 0;
}
赛时:100point
赛后:无
T2
总感觉在AtCoder见过
其实可以用一个临时变量存储当前度数,每次输入加在这个变量上,当它超过一个圆(\(360度\))时,对它\(\%360\)就可以啦!再用一个桶数组存储是否出现,之后枚举\(0->360\) 坑点,算最大距离。
赛时,因忘记首刀同时切在\(0度\)和\(360度\)上,忘记prefix[360] ++了,痛失
12point
贴一下代码
#include <bits/stdc++.h>
using namespace std;
#define fre(c) freopen(c".in","r",stdin);freopen(c".out","w",stdout);
#define ll long long
#define endl "\n"
#define ios ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define cst const
cst ll N = 360 + 5;
ll n, a[N], x, prefix[N], jd = 0, ma = -0x3f3f3f3f, last = -1;
ll read() {
char c;
ll sum = 0;
int f = 1;
c = getchar();
while (!isdigit(c)) {
if (c == '-')
f *= -1;
c = getchar();
}
while (isdigit(c)) {
sum = sum * 10 + (c - '0');
c = getchar();
}
return sum * f;
}
int main() {
ios
// fre("2");
fre("pizza")
n = read();
for (ll i = 1; i <= n; i ++) {
x = read();
jd += x;
jd %= 360;
a[i] = jd;
prefix[a[i]] ++;
}
prefix[0] ++;
prefix[360] ++;
for (int i = 0; i <= 360; i ++) {
if (prefix[i] >= 1 && last != -1) {
ma = max(ma, i - last);
last = i;
}
if (prefix[i] >= 1) {
last = i;
}
}
cout << ma;
return 0;
}
赛时:88point
赛后:100point
T3
看似很复杂的一道问题,实则我们只需要专心用\(O(n)\)的复杂度来统计相同颜色的长度,并在颜色变化时记录:
- 计算能在当前连续块中进行的最大有效操作数
- 每个有效操作可以增加2个记忆碎片
- 更新剩余操作次数
- 处理特殊情况(\(k \neq 2\)且连续块长度为偶数时,连续区间加\(1\))
- 重置连续相同颜色的长度为\(1\)(新颜色的开始)
贴一下代码
#include <bits/stdc++.h>
using namespace std;
#define fre(c) freopen(c".in","r",stdin);freopen(c".out","w",stdout);
#define ll long long
#define endl "\n"
#define ios ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define cst const
cst ll N = 1e5 + 5;
cst ll INF = 0x3f3f3f3f;
ll t;
ll read() {
char c;
ll sum = 0;
int f = 1;
c = getchar();
while (!isdigit(c)) {
if (c == '-')
f *= -1;
c = getchar();
}
while (isdigit(c)) {
sum = sum * 10 + (c - '0');
c = getchar();
}
return sum * f;
}
void fun() {
ll n, m, k, cnt = 0, ans = 0, sum = 0, tmp = 0;
n = read();
m = read();
k = read();
vector<ll> a(n + 2);//懒得memset
for (ll i = 1; i <= n + 1; i ++) {
if (i <= n) {
cin >> a[i];
} else {
a[i] = k + 1;
}
if (a[i] == a[i - 1] || i == 1) {
sum++;
} else {
ans ++;
tmp = m > (sum - 1) / 2 ? (sum - 1) / 2 : m;
ans += tmp * 2;
m -= tmp;
if(k != 2 && !(sum & 1)) {
cnt ++;
}
sum = 1;
}
}
cout << ans + min(m, cnt) << endl;
}
int main() {
fre("art")
t = read();
while(t --) {
fun();
}
return 0;
}
赛时:30point
赛后:100point
T4
很版的一道\(二维dp\)题,每当包包遇到一个食物是,可以判断一下:
\( \left\{ \begin{aligned} &op = 毒食:只能选择吃解毒食物或者不吃 \\ &op = 解毒食:能选择吃或者不吃 \end{aligned} \right. \)
\(op=1\):代表毒食
\(op=0\):代表解毒食
得到以下状态转移方程:
(\(i\)代表从\(1\)到\(n\)的每一种食物,\(tmp\)表示每种食物的美味度)
\( \left\{ \begin{aligned} &op = 1:f[i][1]=max(f[i][1],f[i-1][0]+tmp)\\ &op = 0:f[i][0]=max(f[i][0],max(f[i-1][0],f[i-1][1])+tmp) \end{aligned} \right. \)
可得以下代码:
贴一下代码
#include <bits/stdc++.h>
using namespace std;
#define fre(c) freopen(c".in","r",stdin);freopen(c".out","w",stdout);
#define ll long long
#define endl "\n"
#define ios ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define cst const
cst ll N = 3 * 1e5 + 5;
ll read() {
char c;
ll sum = 0;
int f = 1;
c = getchar();
while (!isdigit(c)) {
if (c == '-')
f *= -1;
c = getchar();
}
while (isdigit(c)) {
sum = sum * 10 + (c - '0');
c = getchar();
}
return sum * f;
}
ll n, op, tmp, f[N][5];
int main() {
fre("taste")
n = read();
for(int i = 1; i <= n; i ++) {
op = read();
tmp = read();
f[i][0] = f[i - 1][0];
f[i][1] = f[i - 1][1];
if(op) {
f[i][1] = max(f[i][1], f[i - 1][0] + tmp);
} else {
f[i][0] = max(f[i][0], max(f[i - 1][0], f[i - 1][1]) + tmp);
}
}
cout << max(f[n][0],f[n][1]);
return 0;
}
赛时:17point(没时间打,只打了个表)
赛后:100point
T5
其实题目意思还是挺明显的
就是要我们把每一道工序看成一个顶点,每道工序看成一条边。
我们来分析样例&1,根据关系可知以下图:
与\(4\)相连的有\(2\)个点。
我们可以用邻接表或链式前向星存图,再\(BFS\)遍历。
贴一下代码
#include <bits/stdc++.h>
using namespace std;
#define fre(c) freopen(c".in","r",stdin);freopen(c".out","w",stdout);
#define ll long long
#define endl "\n"
#define ios ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define cst const
cst int N = 2 * 1e5 + 5;
cst int mod = 1e9 + 7;
queue<int> que;
map<int, int > stp;
int n, m, k, t, op;
int sum;
int ans, tmp, pre, cnt, tot, pos;
ll a[N], f[N];
int head[N], vis[N];
struct edge {
int to, nxt;
} e[N*2];
void add(int x, int y) {
e[++tot] = {y, head[x]};
head[x] = tot;
}
int main() {
// freopen("1.txt", "r", stdin);
freopen("Alchemy.in", "r", stdin);
freopen("Alchemy.out", "w", stdout);
cin >> n >> m;
for(int i = 1, u, v; i <= m; i++) {
scanf("%d%d", &u, &v);
add(u, v);
add(v, u);
}
que.push(1);
f[1] = 1;
stp[1] = 0;
while (!que.empty()) {
tmp = que.front();
vis[tmp] = 2;
que.pop();
for (int i = head[tmp]; i; i = e[i].nxt) {
pos = e[i].to;
if (! stp[pos])
stp[pos] = stp[tmp] + 1;
if (vis[pos] != 2 && stp[pos] >= stp[tmp] + 1) {
f[pos] = (f[pos] + f[tmp]) % mod;
if (! vis[pos]) {
vis[pos] = 1;
que.push(pos);
}
}
}
}
cout << f[n];
return 0;
}
赛时:6point(没时间打,只打了个表)
赛后:100point

浙公网安备 33010602011771号