Problem B Fire-Fighting Hero
题目链接:https://nanti.jisuanke.com/t/41349
题意: 判断消防英雄去其他消防点的最短路径的最大值与消防队去其他消防点的最短路径的最大值中的最小值。
思路: 添加一个顶点0,连接各个消防队所在的救火点,路径长度均设为0,设该顶点为源,即变成了单源最短路径问题。使用两次单源最短路径算法可求出两个最短路径的最大值。比较时将消防队的乘以c进行比较可避免相除操作。
Accepted Code:
/*
* @Author: lzyws739307453
* @Language: C++
*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e3 + 5;
const int inf = 0x3f3f3f3f;
bool vis[MAXN];
int mp[MAXN][MAXN];
int dis[MAXN], e[MAXN], n;
void init() {
memset(dis, 0x3f, sizeof(dis));
memset(vis, false, sizeof(vis));
}
int Spfa(int s) {
init();
queue <int> Q;
Q.push(s);
dis[s] = 0;
while (!Q.empty()) {
int u = Q.front();
Q.pop();
vis[u] = false;
for (int i = 1; i <= n; i++) {
if (mp[u][i] < inf) {
if (dis[i] > dis[u] + mp[u][i]) {
dis[i] = dis[u] + mp[u][i];
if (!vis[i]) {
Q.push(i);
vis[i] = true;
}
}
}
}
}
int max_ = dis[1];
for (int i = 2; i <= n; i++)
max_ = max(max_, dis[i]);
return max_;
}
int main() {
int m, s, k, c, t;
scanf("%d", &t);
while (t--) {
scanf("%d%d%d%d%d", &n, &m, &s, &k, &c);
for (int i = 0; i <= n; i++)
for (int j = 0; j <= n; j++)
mp[i][j] = i != j ? inf : 0;
for (int i = 0; i < k; i++)
scanf("%d", &e[i]);
for (int i = 0; i < m; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
mp[u][v] = mp[v][u] = min(mp[u][v], w);
}
int cnta = Spfa(s);
for (int i = 0; i < k; i++)
mp[0][e[i]] = mp[e[i]][0] = 0;
int cntb = Spfa(0);
if (cnta <= cntb * c)
printf("%d\n", cnta);
else printf("%d\n", cntb);
}
return 0;
}
Problem E Magic Master
题目链接:https://nanti.jisuanke.com/t/41352
题意: 判断开始时拍的顺序,经过一些操作,使其最后从上到下为递减状态。
思路: 根据所给的规则直接反着模拟即可。
Accepted Code:
/*
* @Author: lzyws739307453
* @Language: C++
*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 4e7 + 5;
queue <int> Q;
int spt[MAXN];
int main() {
int t, n, m, q, k;
scanf("%d", &t);
while (t--) {
scanf("%d%d%d", &n, &m, &q);
Q.push(n);
for (int i = n - 1; i >= 1; i--) {
for (int j = 0; j < m; j++) {
Q.push(Q.front());
Q.pop();
}
Q.push(i);
}
for (int i = n; i >= 1; i--) {
spt[i] = Q.front();
Q.pop();
}
while (q--) {
scanf("%d", &k);
printf("%d\n", spt[k]);
}
}
return 0;
}
Problem G Pangu Separates Heaven and Earth
题目链接:https://nanti.jisuanke.com/t/41354
题意: 如果输入的是1,输出18000,否则输出0。
思路: 签到题。
Accepted Code:
/*
* @Author: lzyws739307453
* @Language: C++
*/
#include <bits/stdc++.h>
using namespace std;
int main() {
int t, n;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
printf(n != 1 ? "0\n" : "18000\n");
}
return 0;
}
Problem H The Nth Item
题目链接:https://nanti.jisuanke.com/t/41355
题意: 给定一个序列F(n)=3F(n-1)+2F(n-2)(n>=2),F(0)=0, F(1)=1。Q次询问,将每次询问第N项对998244353取模的值异或起来。
思路: 可以通过打表发现到最后,每两个异或值是相互交题出现的,故当出现交替出现的时候就可以退出询问,根据剩余询问的就可确定最后的答案。计算F[n]可利用矩阵加速。
Accepted Code:
/*
* @Author: lzyws739307453
* @Language: C++
*/
#include <bits/stdc++.h>
using namespace std;
const int MOD = 998244353;
struct Mat {
long long mat[3][3];
Mat() {
memset(mat, 0, sizeof(mat));
}
};
Mat Mul(Mat a, Mat b) {
Mat c;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
c.mat[i][j] = (c.mat[i][j] + (a.mat[i][k] * b.mat[k][j]) % MOD) % MOD;
}
}
}
return c;
}
long long slove(long long k) {
Mat A, Ans;
A.mat[0][0] = 3, A.mat[0][1] = 1;
A.mat[1][0] = 2, A.mat[1][1] = 0;
Ans.mat[0][0] = Ans.mat[1][1] = 1;
while (k) {
if (k & 1)
Ans = Mul(Ans, A);
A = Mul(A, A);
k >>= 1;
}
return Ans.mat[0][1];
}
int main() {
int n, tmp = -1;
long long N, NN, A, ans;
long long a = -1, b = -1, c = -1;
scanf("%d%lld", &n, &N);
ans = A = slove(N);
for (int i = 1; i < n; i++) {
NN = N ^ (A * A);
A = slove(NN);
N = NN;
ans ^= A;
if (!~a) a = ans;
else if (!~b) b = ans;
else if (!~c) c = ans;
else {
a = b, b = c, c = ans;
if (c == a) {
tmp = i;
break;
}
}
}
if (tmp != -1) {
if ((n - tmp) & 1)
printf("%lld\n", a);
else printf("%lld\n", b);
}
else printf("%lld\n", ans);
return 0;
}