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[jw]+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;
}

  

 

  

posted @ 2025-12-09 22:03  河南工业大学算法协会  阅读(32)  评论(0)    收藏  举报