河南萌新联赛2024第(二)场:南阳理工学院

国际旅行Ⅰ

思路:排序后直接输出

void solve() {
    int n, m, q;
    cin >> n >> m >> q;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; ++i) cin >> a[i];
    vector<vector<int> > ve(n + 1);
    for (int i = 1; i <= m; ++i) {
        int u, v;
        cin >> u >> v;
        ve[u].push_back(v), ve[v].push_back(u);
    }
    sort(a.begin() + 1, a.end());
    while (q --) {
        int k;
        cin >> k;
        cout << a[k] << '\n';
    }
}

A*BBBB

思路:

b的每一位数相同,将b的每一位拆分,可以将a * b看作a * b[0] + a * b[1] * 10 + a * b[2] * 100 + ...

可以用高精度乘法O(n)计算a乘上b[0]

但是如果对于加法部分这样枚举加是O(n2)的,所以考虑优化

已知bn为b的位数

将bn个数用加法运算方法依次从上往下表示出来,从低位开始加法计算

可以发现每一位上的bn个数的和可以用前缀和维护,然后模拟加法过程即可

(手动画画加法运算过程就可以看出加的哪些数)

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define PII pair<int, int>
const int N = 1e5 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;

vector<int> mul(vector<int> A, int b) {
    vector<int> C;
    int t = 0;
    for (int i = 0; i < A.size() || t; ++i) {
        if (i < A.size()) t += A[i] * b;
        C.push_back(t % 10);
        t /= 10;
    }
    while (C.size() > 1 && C.back() == 0) C.pop_back();
    return C;
}


void solve() {
    string a, b;
    cin >> a >> b;
    vector<int> aa, bb;
    for (int i = a.size() - 1; i >= 0; --i) aa.push_back(a[i] - '0');
    for (int i = b.size() - 1; i >= 0; --i) bb.push_back(b[i] - '0');
    if (a == "0" || b == "0") {
        cout << "0\n";
        return ;
    }

    vector<int> cc = mul(aa, bb[0]);
    int cn = cc.size();
    vector<int> sum(cn + 1);
    std::reverse(cc.begin(), cc.end());
    for (int i = 1; i <= cn; ++i) {
        sum[i] = sum[i - 1] + cc[i - 1];
    }
    auto get = [=] (int l, int r) {
        return sum[r] - sum[l - 1];
    };
    int m = bb.size() + cc.size() - 1;
    vector<int> ans;
    int t = 0;
    for (int i = m, l = cn + 1, r = cn; i >= 1; --i) {
        r = min(r, i);
        if (l > 1) l --;
        int num = get(l, r);
        t += num;
        ans.push_back(t % 10);
        t /= 10;
    }
    if (t > 0) ans.push_back(t);
    std::reverse(ans.begin(), ans.end());
    for (auto v:ans) cout << v;
    cout << '\n';
}



signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }

    return 0;
}

“好”字符

思路:

字符串哈希或kmp

将b串后面再跟一个b串,这样操作后的串里长度为n的子串都为b的循环同构串

只有26个字符,分别考虑每个字符是否是好的

对于一个字符,将其余字符都设为一样,现在问题就变为操作后的b串中是否存在为a的子串

用字符串哈希或kmp都可以处理

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define PII pair<int, int>
const int N = 2e6 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;

int kmp(string text, string pattern) {
    int n = text.size(), m = pattern.size();
    if (m == 0) {
        return 0;
    }
    vector<int> next(m);
    for (int i = 1, j = 0; i < m; i++) {
        while (j > 0 && pattern[i] != pattern[j]) {
            j = next[j - 1];
        }
        if (pattern[i] == pattern[j]) {
            j++;
        }
        next[i] = j;
    }
    for (int i = 0, j = 0; i < n; i++) {
        while (j > 0 && text[i] != pattern[j]) {
            j = next[j - 1];
        }
        if (text[i] == pattern[j]) {
            j++;
        }
        if (j == m) {
            return i - m + 1;
        }
    }
    return -1;
}

void solve() {
    int n;
    cin >> n;
    string a, b;
    cin >> a >> b;
//    swap(a, b);
    b = b + b;
    vector<string> bb(26);
    vector<string> aa(26);
    for (int i = 0; i < 26; ++i) {
        char op = 'a' + i;
        bb[i] = b;
        int cnta = 0, cntb = 0;
        for (int j = 0; j < bb[i].size(); ++j) {
            if (bb[i][j] == op) {
                cntb ++;
                continue;
            }
            bb[i][j] = '.';
        }
        aa[i] = a;
        for (int j = 0; j < aa[i].size(); ++j) {
            if (aa[i][j] == op) {
                cnta ++;
                continue;
            }
            aa[i][j] = '.';
        }
        if (cnta * 2 != cntb || cnta == 0) {
            aa[i].clear();
        }
    }
    int ans = 0;
    for (int t = 0; t < 26; ++t) {
        if (aa[t].empty()) continue;
        if (kmp(bb[t], aa[t]) != -1) ans ++;
    }
    cout << ans << '\n';
}


signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
//    cin >> T;
    while (T--) {
        solve();
    }

    return 0;
}
#include <bits/stdc++.h>

using namespace std;

#define ull unsigned long long
#define int long long
#define PII pair<int, int>
//const int N = 2e6 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;

const int N = 2e6 + 5; // 最大字符串的个数
const int M = 2e6 + 10; // 题目中字符串的最大长度
const ull base = 131; // 131,13331不容易哈希碰撞

// p[i]:表示p的i次方
// h[i]:表示s[1~i]的哈希值,如h[2]表示字符串s前两个字符组成字符串的哈希值
ull p[N], h[N];

//int n;

// 预处理hash函数的前缀和,时间复杂度O(n)
void init(string s) {
    //  下标从1开始
    int n = s.size() - 1;
    // p^0=1,空串哈希值为0
    p[0] = 1, h[0] = 0;
    for (int i = 1; i <= n; i++) {
        p[i] = p[i - 1] * base;
        h[i] = h[i - 1] * base + s[i]; // 前缀和计算公式
    }
}

// 计算s[l~r](子串)的hash值,时间复杂度O(1)
ull get(int l, int r) {
    return h[r] - h[l - 1] * p[r - l + 1]; // 区间和计算字串的hash值
}

// 判断s中的两个子串是否相同
bool substr(int l1, int r1, int l2, int r2) {
    return get(l1, r1) == get(l2, r2);
}

//  求ss的哈希值(下标从0开始)
ull gethash(string ss) {
    ull ret = 0;
    for (int i = 0; i < ss.size(); ++i)
        ret = ret * base + (ull) ss[i];
    return ret;
}

void solve() {
    int n;
    cin >> n;
    string a, b;
    cin >> a >> b;
    b = b + b;
    vector<string> bb(26);
    vector<string> aa(26);
    for (int i = 0; i < 26; ++i) {
        char op = 'a' + i;
        bb[i] = ' ' + b;
        int cnta = 0, cntb = 0;
        for (int j = 0; j < bb[i].size(); ++j) {
            if (bb[i][j] == op) {
                cntb++;
                continue;
            }
            bb[i][j] = '.';
        }
        aa[i] = a;
        for (int j = 0; j < aa[i].size(); ++j) {
            if (aa[i][j] == op) {
                cnta++;
                continue;
            }
            aa[i][j] = '.';
        }
        if (cnta * 2 != cntb || cnta == 0) {
            aa[i].clear();
        }
    }
    int ans = 0;
    for (int t = 0; t < 26; ++t) {
        if (aa[t].empty()) continue;
        init(bb[t]);
        int hasha = gethash(aa[t]);
        for (int i = 1; i <= n; ++i) {
            int hashb = get(i, i + n - 1);
            if (hasha == hashb) {
                ans ++;
                break;
            }
        }
    }
    cout << ans << '\n';
}


signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
//    cin >> T;
    while (T--) {
        solve();
    }

    return 0;
}

水灵灵的小学弟

void solve() {
    int a, b;
    cin >> a >> b;
    cout << "DHY\n";
}

lxy的通风报信

思路:

首先军队数量最多为50,那么可以求出两两军队之间到达的最短距离,复杂度为50 * n * m

然后求最小生成树即可

#include <bits/stdc++.h>

using namespace std;

//#define int long long
#define PII pair<int, int>
const int N = 1e6 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;

int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};

struct E {
    int u, v, w;
    bool operator<(const E &e) const {
        return w < e.w;
    }
};
int fa[100];
int find(int x) {
    if (x != fa[x]) fa[x] = find(fa[x]);
    return fa[x];
}
void solve() {
    int n, m;
    cin >> n >> m;
    int cnt = 0;
    map<int, int> id;
    vector<string> s(n);
    for (int i = 0; i < n; ++i) {
        cin >> s[i];
        for (int j = 0; j < m; ++j) {
            if (s[i][j] == '*') {
                id[i * m + j] = ++cnt;
            }
        }
    }
    vector<vector<int> > dis(cnt + 1, vector<int> (cnt + 1, INT32_MAX));
    
    vector<int> st(n * m + 10);
    
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            if (s[i][j] == '*') {
                int stid = i * m + j;
                queue<PII> q;
                q.push({stid, 0});
                st[stid] = stid;
                while (q.size()) {
                    auto [uid, d] = q.front();
                    q.pop();
                    int x = uid / m, y = uid % m;
                    if (s[x][y] == '*') dis[id[stid]][id[uid]] = min(dis[id[stid]][id[uid]], d), dis[id[uid]][id[stid]] = min(dis[id[uid]][id[stid]], d);
                    for (int k = 0; k < 4; ++k) {
                        int xx = x + dx[k], yy = y + dy[k], vid = xx * m + yy;
                        if (xx < 0 || xx >= n || yy < 0 || yy >= m || st[vid] == stid || s[xx][yy] == '#') continue;
                        q.push({vid, d + 1});
                        st[vid] = stid;
                    }
                }
            }
        }
    }
    vector<E> edge;
    for (int i = 1; i <= cnt; ++i) {
        for (int j = i + 1; j <= cnt; ++j) {
            if (dis[i][j] == INT32_MAX) {
                cout << "No";
                return ;
            }
            edge.push_back({i, j, dis[i][j]});
        }
    }
    sort(edge.begin(), edge.end());

    for (int i = 1; i <= cnt; ++i) fa[i] = i;

    int sum = 0;

    for (int i = 0; i < edge.size(); ++i) {
        int u = find(edge[i].u), v = find(edge[i].v);
        if (u == v) continue;
        fa[v] = u;
        sum += edge[i].w;
        cnt --;
        if (cnt <= 1) break;
    }
    if (cnt <= 1) {
        cout << sum;
    } else cout << "No\n";

}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
//    cin >> T;
    while (T--) {
        solve();
    }

    return 0;
}

狼狼的备忘录

思路:

数据不大,狠狠暴力

只要有一个串为另一个串的后缀就不要

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define PII pair<int, int>
const int N = 1e5 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;

void solve() {
    int n;
    cin >> n;
    map<string, set<string>> f;
    map<string, set<string> > g;
    auto check = [&] (string na, string u) {
        for (auto v:g[na]) {
            if (u.size() > v.size()) {
                bool ok = true;
                for (int j = u.size() - 1, i = v.size() - 1; i >= 0; --j, --i) {
                    if (u[j] != v[i]) {
                        ok = false;
                        break;
                    }
                }
                if (ok) {
                    g[na].erase(v);
                    return true;
                }
            } else if (u.size() < v.size()) {
                bool ok = true;
                for (int j = u.size() - 1, i = v.size() - 1; j >= 0; --j, --i) {
                    if (u[j] != v[i]) {
                        ok = false;
                        break;
                    }
                }
                if (ok) return false;
            }
        }
        return true;
    };
    for (int i = 0; i < n; ++i) {
        string na;
        cin >> na;
        int k;
        cin >> k;
        for (int j = 0; j < k; ++j) {
            string x;
            cin >> x;
            f[na].insert(x);
        }
    }

    for (auto [na, ve]:f) {
        for (auto v:ve) {
            if (check (na, v)) g[na].insert(v);
        }
    }
    cout << g.size() << '\n';
    for (auto [na, ve]:g) {
        cout << na << ' ';
        cout << ve.size() << ' ';

        for (auto v:ve) cout << v << ' ';
        cout << '\n';
    }
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
//    cin >> T;
    while (T--) {
        solve();
    }

    return 0;
}

重生之zbk要拿回属于他的一切

void solve() {
    int n;
    cin >> n;
    string s;
    cin >> s;
    string a = "chuan";
    int ans = 0;
    for (int i = 0; i + 4 < s.size(); ++i) {
        for (int j = 0, ii = i; j < a.size(); ++j, ++ii) {
            if (a[j] != s[ii]) break;
            if (j == a.size() - 1) ans ++, i += 4;
        }
    }
    cout << ans;
}

这是签到

思路:

按照给的公式,枚举算所有排列

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define PII pair<int, int>
const int N = 1e5 + 5, mod = 998244353, Mod = 1e9 + 7, inf = 1e18;


void solve() {
    int n, m;
    cin >> n >> m;
    int ma = max(n, m);
    vector<vector<int> > ve(ma + 1, vector<int> (ma + 1, 0));
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j) cin >> ve[i][j];

    int ans = LLONG_MAX;
//    ans = ve[1][1];
//    if (ma >= 2) ans = min(ans, ve[1][1] * ve[2][2] - ve[1][2] * ve[2][1]);
////    cout << ve[1][1] * ve[2][2] - ve[1][2] * ve[2][1] << '\n';
//    if (ma >= 3) ans = min(ans, ve[1][1] * ve[2][2] * ve[3][3] + ve[1][2] * ve[2][3] * ve[3][1] + ve[1][3] * ve[2][1] * ve[3][2] -
//    ve[1][3] * ve[2][2] * ve[3][1] - ve[1][1] * ve[2][3] * ve[3][2] - ve[1][2] * ve[2][1] * ve[3][3]);
    for (int t = 1; t <= ma; ++t) {
        vector<int> a(t);
        int res = 0;
        for (int i = 0; i < t; ++i) a[i] = i + 1;
        do {
            int cnt = 0;
            for (int i = 0; i < t; ++i) {
                for (int j = i + 1; j < t; ++j) {
                    cnt += (a[i] > a[j]);
                }
            }

            int sum = 1;
            for (int i = 0, j = 1; i < t; ++i, ++j) {
                sum *= ve[j][a[i]];
            }
            if (cnt % 2) sum = -sum;
            res += sum;
        }while (next_permutation(a.begin(), a.end()));
//        cout << res << '\n';
        ans = min(ans, res);
    }
    cout << ans;
}



signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
//    cin >> T;
    while (T--) {
        solve();
    }

    return 0;
}

 

posted @ 2024-07-24 22:18  bible_w  阅读(17)  评论(0编辑  收藏  举报