CSP-J 2023 参考代码
校内一位高手做了 CSP-S 的参考代码,于是本人跟风做一个 J 组的。
下列代码目前只在洛谷测试过,并不保证对于 CCF 官方数据的正确性。下列代码已经在 CCF 官方数据下测试通过,正确性可以保证。
P9748 [CSP-J 2023] 小苹果
按照题意模拟很容易找到规律,从而得到一个 的算法。注意两个问题不能同时算出,必须要额外开一个 来算第二问。
#include <iostream>
using namespace std;
long long n, res1, res2, tmp;
int main(void) {
cin >> n;
tmp = n;
while (tmp > 3) {
tmp -= (tmp + 2) / 3;
res1++;
}
cout << res1 + tmp << ' ';
while (n % 3 != 1) {
n -= (n + 2) / 3;
res2++;
}
cout << ++res2;
return 0;
}
P9749 [CSP-J 2023] 公路
“油不够了就要加油”,这是常识中的常识。
或许你可能会想,要是实际开车的时候,能等到油不够了就“回到”油价最少的车站加油,那该多好啊!
思路就在于此,开一个 minn
记录到达过的车站中油价最少值,每次油不够了就直接加上即可。
注意需要前进的公里数可能无法整除每升油可以走的公里数,留心一下由此带来的加减运算。
#include <iostream>
#define int long long
using namespace std;
const int maxn = 1e5 + 10, inf = 1e18;
int n, d;
int v[maxn], a[maxn];
int sumv[maxn], tot, res, price = inf;
inline void gmi(int &x, int y) { x > y ? x = y : 0; }
signed main(void) {
cin >> n >> d;
for (int i = 1; i <= n - 1; i++) {
cin >> v[i];
sumv[i] = sumv[i - 1] + v[i]; //总共要走的公里数
}
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n - 1; i++) {
gmi(price, a[i]);
if (tot * d < sumv[i]) {
res += (sumv[i] - tot * d + d - 1) / d * price;
tot += (sumv[i] - tot * d + d - 1) / d; //买的油总量
}
}
cout << res;
return 0;
}
P9750 [CSP-J 2023] 一元二次方程
分类讨论的内容很多,所以直接在注释里面写了。
有一点小技巧:若 则把 全部变为相反数,从而保持 为正数。具体作用请读者自行思考。
#include <iostream>
#include <algorithm>
#include <cmath>
#define int long long
#define double long double
using namespace std;
const double eps = 1e-8;
int T, m;
inline auto sqrtDivide(int x) { //根号化简
bool flag = true;
int inte = 1;
while (flag) {
flag = false;
for (int i = 2; i * i <= x; i++) {
if (x % (i * i) == 0) {
x /= (i * i);
inte *= i;
flag = true;
break;
}
}
}
return make_pair(inte, x);
}
inline void integerSolve(int a, int b, int delta) {
//num -> 分子 deno -> 分母
int num = -b + (int)sqrt(delta), deno = 2 * a;
int gcd = __gcd(abs(num), abs(deno));
//类型 1: 分子为 0
if (num == 0) cout << 0;
//类型 2:分母可以被约去
else if (deno == gcd) cout << num / gcd;
//类型 3:分母约去后剩下 -1
else if (-deno == gcd) cout << -num / gcd;
//类型 4:正常情况。
else cout << num / gcd << '/' << deno / gcd;
}
inline void floatSolve(int a, int b, int delta) {
int inte = sqrtDivide(delta).first, delt = sqrtDivide(delta).second;
int gcd = __gcd(abs(inte), abs(2 * a));
//q1 != 0,先按照有理数格式输出
if (b != 0) {
integerSolve(a, b, 0);
cout << '+';
}
//类型 1: 约分后整数部分和分母均为 1
if (inte == abs(2 * a)) cout << "sqrt(" << delt << ')' << '\n';
//类型 2:分子可以被约去
else if (inte == gcd) cout << "sqrt(" << delt << ")/" << 2 * a / gcd << '\n';
//类型 3:分母可以被约去
else if (abs(2 * a) == gcd) cout << inte / gcd << "*sqrt(" << delt << ')' << '\n';
//类型 4:正常情况。
else cout << inte / gcd << "*sqrt(" << delt << ")/" << 2 * a / gcd << '\n';
}
signed main(void) {
cin >> T >> m;
while (T--) {
int a, b, c;
cin >> a >> b >> c;
if (a < 0) a = -a, b = -b, c = -c; //保证 a 为正数
int delta = b * b - 4 * a * c;
if (delta < 0) {
cout << "NO" << '\n';
continue;
} else {
double sqD = sqrt(delta);
//sqrt(delta) 的整数与否直接决定是否要输出根号
if (abs(floor(sqD) - sqD) < eps) integerSolve(a, b, delta), cout << '\n';
else floatSolve(a, b, delta);
}
}
return 0;
}
P9751 [CSP-J 2023] 旅游巴士
由于每隔 秒才会有巴士,所以我们可以根据最短路 的结果拆点建立分层图;
此外到达和离开时间都必须为 的整数倍,所以对应修改一下边权,据此对 dijkstra 算法进行微小调整即可使用。
这道题的拆点和分层图和网络流的某些经典模型相似,这就是 J 组的实力吗……
#include <iostream>
#include <cstring>
#include <bitset>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/priority_queue.hpp>
//上面两个 pb_ds 的头文件是为了调用一个“高级一点”的优先队列,其底层为配对堆
//当然直接用普通的二叉堆也能过
#define int long long
#define pii pair<int, int>
using namespace std;
using namespace __gnu_pbds;
const int maxn = 5e4 + 10, maxk = 150;
const int inf = 0x3f3f3f3f3f3f3f3f;
__gnu_pbds::priority_queue<pii, greater<pii>, pairing_heap_tag> Q;
bitset<maxn> vis[maxk]; //比普通的 bool 数组更快的神奇 STL
int n, m, k;
int dis[maxk][maxn];
int head[maxn], nxt[maxn], to[maxn], val[maxn], cnt;
inline void add(int u, int v, int w) {
nxt[cnt] = head[u], to[cnt] = v, val[cnt] = w, head[u] = cnt++;
}
inline int calc(int x, int k) { //为了处理一点复杂的取整问题
if (x % k > 0) return x / k + 1;
return x / k;
}
inline void bfs() {
memset(dis, 0x3f, sizeof(dis));
dis[0][1] = 0;
Q.push({0, 1});
while (!Q.empty()) {
int mov = Q.top().first, u = Q.top().second;
Q.pop();
if (vis[mov % k][u]) continue;
vis[mov % k][u] = true;
for (int i = head[u]; ~i; i = nxt[i]) {
int v = to[i], dec = mov + 1;
if (val[i] - mov > 0)
dec += calc(val[i] - mov, k) * k;
if (dis[dec % k][v] > dec) {
dis[dec % k][v] = dec;
Q.push({dis[dec % k][v], v});
}
}
}
}
signed main() {
memset(head, -1, sizeof(head));
cin >> n >> m >> k;
for (int i = 1; i <= m; i++) {
int u, v, w;
cin >> u >> v >> w;
add(u, v, w);
}
bfs();
if (dis[0][n] >= inf) cout << -1;
else cout << dis[0][n];
return 0;
}
本文作者:Coel's Blog
本文链接:https://www.cnblogs.com/Coel-Flannette/p/17793261.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步