2025年河南工业大学2025新生周赛 (7)
A 回声
将连续的字母和连字符视为同一个单词
bool isWordChar(char c) {
if ((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
c == '-') {
return true;
}
return false;
}
从头到尾遍历,并存单词即可
int main() {
string s;
cin>>s;
vector<string> words;
string cur;
for (int i = 0; i < (int)s.size(); ++i) {
char c = s[i];
if (isWordChar(c)) {
cur += c;
} else {
if (!cur.empty()) {
words.push_back(cur);
cur.clear();
}
}
}
if (!cur.empty()) {
words.push_back(cur);
}
int n = words.size();
int start = n - 3;
if (start < 0) start = 0;
for (int i = start; i < n; ++i) {
if (i > start) cout << ' ';
cout << words[i];
}
cout << '\n';
return 0;
}
B 挂谷集
读题可知需要求凸集面积,也就是给定正三角形的高求面积。
最初的数据范围会使double(八位浮点)损失精度,已修改
void solve(){
double x; scanf("%lf",&x);
printf("%.2lf",x*x/sqrt(3));
}
C 身份证校验
根据题目进行模拟即可,实现方法有多种,此处给出一种
void solve(){
int ans=0,arr[]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
string ID,map="10X98765432";
cin>>ID;
for(int i=0; i<17; i++){
ans += ( ID[i] - '0' ) * arr[i];
}
cout << ID << map[ans%11] <<'\n';
}
D Starlight
根据题意,判断两边的大小关系,可以判断点是否在函数所包围封闭图形内部。此处需要注意正负号,因此可以统一加绝对值来处理。
void solve() {
double x, y, a;
cin>> x >> y >> a;
const double eps = 1e-6;
double left = pow(fabs(x), 2.0 / 3.0) + pow(fabs(y), 2.0 / 3.0);
double right = pow(a, 2.0 / 3.0);
double diff = left - right;
if (fabs(diff) < eps) {
cout << "Non Non Da Yo\n";
} else if (diff < 0) {
cout << "Position Zero!\n";
} else {
cout << "Fly Me to the Star\n";
}
}
E 小圈子
本题考察并查集,数据范围不需要使用路径压缩、按秩合并。
#include <bits/stdc++.h>
using namespace std;
int parent[1010];
int findRoot(int x) {
while (parent[x] != x) {
x = parent[x];
}
return x;
}
bool unite(int a, int b) {
int ra = findRoot(a);
int rb = findRoot(b);
if (ra == rb) return false;
parent[rb] = ra;
return true;
}
void solve(){
int N, M;
cin >> N >> M;
for (int i = 1; i <= N; ++i) {
parent[i] = i;
}
int groups = N;
for (int i = 0; i < M; ++i) {
int A, B;
cin >> A >> B;
if (unite(A, B)) {
groups--;
}
}
cout << groups << "\n";
}
int main() {
ios::sync_with_stdio(false); cin.tie(nullptr);
int T; cin>>T;
while (T--) solve();
return 0;
}
F 世界线跃迁
本题考察单源最短路,使用Dijkstra算法即可满足题目复杂度。
AC代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, s;
if (!(cin >> n >> s)) return 0;
vector<vector<int>> g(n, vector<int>(n));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
cin >> g[i][j];
}
}
const int INF = 0x3f3f3f3f;
vector<int> dist(n, INF);
vector<bool> vis(n, false);
dist[s] = 0;
for (int i = 0; i < n; ++i) {
int u = -1, mind = INF;
for (int j = 0; j < n; ++j) {
if (!vis[j] && dist[j] < mind) {
mind = dist[j];
u = j;
}
}
if (u == -1) break;
vis[u] = true;
for (int v = 0; v < n; ++v) {
if (g[u][v] > 0 && dist[u] + g[u][v] < dist[v]) {
dist[v] = dist[u] + g[u][v];
}
}
}
bool first = true;
for (int i = 0; i < n; ++i) {
if (i == s) continue;
if (!first) cout << ' ';
first = false;
if (dist[i] == INF) cout << -1;
else cout << dist[i];
}
cout << '\n';
return 0;
}
G 能量分配
本题为动态规划问题中经典的01背包问题。
状态转移方程为 dp[j]=max(dp[j], dp[j−w]+v)
for (int i = 1; i <= N; ++i) {
for (int j = E; j >= w[i]; --j) {
dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
}
}
AC代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int E, N;
while (cin >> E >> N) {
if (E == 0 && N == 0) break;
vector<int> dp(E + 1, 0);
for (int i = 0; i < N; ++i) {
int w, v;
cin >> w >> v;
for (int j = E; j >= w; --j) {
dp[j] = max(dp[j], dp[j - w] + v);
}
}
cout << dp[E] << '\n';
}
return 0;
}
H 耐久魔法
本题考查线段树
#include <bits/stdc++.h>
using namespace std;
constexpr int N = 405;
constexpr int MOD = 1000000007;
struct Node {
int id;
int w;
};
int n, m;
int ans[N];
int dp[N][N];
int s1[N][N], s2[N][N];
bool used[N];
Node a[N];
inline int addMod(int x, int y) {
x += y;
return (x >= MOD) ? x - MOD : x;
}
inline void incMod(int &x, int y) {
x += y;
if (x >= MOD) x -= MOD;
}
int qPow(int x, int y) {
int res = 1;
while (y) {
if (y & 1) res = 1LL * res * x % MOD;
x = 1LL * x * x % MOD;
y >>= 1;
}
return res;
}
inline bool cmpNode(const Node &x, const Node &y) {
return x.w < y.w;
}
// 原 f(l, r) 函数
inline int F(int l, int r) {
return (l * (l + 1)
+ (n - r + 1) * (n - r + 2)
+ (r - l - 1) * (r - l)) / 2;
}
int main() {
if (scanf("%d %d", &n, &m) != 2) {
return 0;
}
used[n + 1] = true;
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i].w);
a[i].id = i;
}
sort(a + 1, a + n + 1, cmpNode);
// 预处理 dp
for (int i = n, last; i >= 1; --i) {
last = 0;
used[a[i].id] = true;
for (int j = 1; j <= n + 1; ++j) {
if (used[j]) {
dp[last][j] += a[i].w - a[i - 1].w;
last = j;
}
}
}
ans[1] = 1LL * a[n].w * qPow(n * (n + 1) / 2, m) % MOD;
for (int i = 2; i <= n; ++i) {
ans[i] = ans[1];
}
// 做 m 次转移
for (int step = 1; step <= m; ++step) {
// 计算前缀和 s1, s2
for (int j = 0; j <= n; ++j) {
for (int k = n + 1; k > j + 1; --k) {
int val = dp[j][k];
s1[j][k] = addMod(j ? s1[j - 1][k] : 0, 1LL * val * j % MOD);
s2[j][k] = addMod(k <= n ? s2[j][k + 1] : 0,
1LL * val * (n - k + 1) % MOD);
}
}
for (int j = 0; j <= n; ++j) {
for (int k = j + 2; k <= n + 1; ++k) {
int val = 1LL * dp[j][k] * F(j, k) % MOD;
if (j) incMod(val, s1[j - 1][k]);
if (k <= n) incMod(val, s2[j][k + 1]);
dp[j][k] = val;
}
}
}
// 统计答案
for (int i = 0; i <= n; ++i) {
for (int j = i + 2; j <= n + 1; ++j) {
for (int k = i + 1; k < j; ++k) {
incMod(ans[k], MOD - dp[i][j]);
}
}
}
for (int i = 1; i <= n; ++i) {
printf("%d ", ans[i]);
}
return 0;
}

浙公网安备 33010602011771号