AtCoder Beginner Contest 284

A - Sequence of Strings (abc284 a)

题目大意

顺序给定\(n\)个字符串,倒着顺序输出。

解题思路

模拟即可。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

int main(void) {
    ios::sync_with_stdio(false); 
    cin.tie(0); cout.tie(0);
    int n;
    cin >> n;
    vector<string> qwq(n);
    for(auto &i : qwq)
        cin >> i;
    reverse(qwq.begin(), qwq.end());
    for(auto &i : qwq)
        cout << i << '\n';

    return 0;
}



B - Multi Test Cases (abc284 b)

题目大意

给定\(n\)个数,问其奇数的个数。

解题思路

模拟即可。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

int main(void) {
    ios::sync_with_stdio(false); 
    cin.tie(0); cout.tie(0);
    int t;
    cin >> t;
    while(t--){
        int n;
        cin >> n;
        int ans = 0;
        while(n--){
            int x;
            cin >> x;
            ans += (x & 1);
        }
        cout << ans << '\n';
    }

    return 0;
}



C - Count Connected Components (abc284 c)

题目大意

给定一张图,问连通块个数。

解题思路

并查集维护连通性即可。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

class dsu {
  public:
  vector<int> p;
  int n;

  dsu(int _n) : n(_n) {
    p.resize(n);
    iota(p.begin(), p.end(), 0);
  }

  inline int get(int x) {
    return (x == p[x] ? x : (p[x] = get(p[x])));
  }

  inline bool unite(int x, int y) {
    x = get(x);
    y = get(y);
    if (x != y) {
      p[x] = y;
      return true;
    }
    return false;
  }
};

int main(void) {
    ios::sync_with_stdio(false); 
    cin.tie(0); cout.tie(0);
    int n, m;
    cin >> n >> m;
    dsu d(n);
    for(int i = 0; i < m; ++ i){
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        d.unite(u, v);
    }
    int ans = 0;
    for(int i = 0; i < n; ++ i)
        ans += (d.get(i) == i);
    cout << ans << '\n';



    return 0;
}



D - Happy New Year 2023 (abc284 d)

题目大意

给定一个数\(N = p^2q\),其中 \(pq\)为质数,问 \(pq\)是多少。

解题思路

注意\(N \leq 9 \times 10^{18}\),预处理质数到\(3e6\),而不能是 \(1e6\)

枚举\(p\),因为题意保证了 \(N\)一定是 \(p^2q\)的形式,所以一旦 \(N \mod p^2 == 0\)就找到解了, \(q\)也一定是质数。

\(p\)枚举到 \(3e6\)后,再往上时 \(q\)的大小是小于 \(1e6\)的,所以\(p\)枚举到\(3e6\)后我们改为枚举 \(q\),进行剩下的情况的判断即可。

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = unsigned long long;
#define FOR(i, x, y) for (decay<decltype(y)>::type i = (x), _##i = (y); i < _##i; ++i)
#define FORD(i, x, y) for (decay<decltype(x)>::type i = (x), _##i = (y); i > _##i; --i)

const LL p_max = 3E6 + 100;
LL pr[p_max], p_sz;
void get_prime() {
    static bool vis[p_max];
    FOR (i, 2, p_max) {
        if (!vis[i]){
            pr[p_sz++] = i;
        }
        FOR (j, 0, p_sz) {
            if (pr[j] * i >= p_max) break;
            vis[pr[j] * i] = 1;
            if (i % pr[j] == 0) break;
        }
    }
}

int main(void) {
    ios::sync_with_stdio(false); 
    cin.tie(0); cout.tie(0);
    get_prime();
    int t;
    cin >> t;
    while(t--){
        LL n;
        cin >> n;
        FOR(i, 0, p_sz){
            LL p = pr[i];
            LL pp = p * p;
            if (n % p == 0){
                LL tmp = n / p;
                LL sq = sqrt(tmp);
                if (sq * sq == tmp){
                    cout << sq << ' ' << p << '\n';
                    break;
                }
            }
            if (n % pp == 0){
                LL tmp = n / pp;
                cout << p << ' ' << tmp << '\n';
                break;
            }
        }
    }

    return 0;
}



E - Count Simple Paths (abc284 e)

题目大意

给定一张图,点度数不超过\(10\)。问从\(1\)号点(编号从 \(1\)开始)的简单路径(不经过重复点)条数 \(k\),输出 \(\min(k, 10^6)\)

解题思路

直接对原图进行\(DFS\),由于每搜到一个状态就是一条未搜过的路径,因此搜到 \(10^6\)后直接退出搜索即可。

由于点度数小于\(10\),所以每次能在不超过 \(10\)的代价找到新的一条路径,总的时间复杂度是 \(O(10^7)\)

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;

const int up = 1e6;

int main(void) {
    ios::sync_with_stdio(false); 
    cin.tie(0); cout.tie(0);
    int n, m;
    cin >> n >> m;
    vector<vector<int>> edge(n);
    for(int i = 0; i < m; ++ i){
        int u, v;
        cin >> u >> v;
        -- u;
        -- v;
        edge[u].push_back(v);
        edge[v].push_back(u);
    }
    int ans = 0;
    vector<int> visit(n, 0);
    function<void(int)> dfs = [&](int u){
        visit[u] = 1;
        ++ ans;
        if (ans >= up)
            return;
        for(auto &v : edge[u]){
            if (visit[v])
                continue;
            dfs(v);
            if (ans >= up)
                return;
        }
        visit[u] = 0;
    };
    dfs(0);
    cout << ans << '\n';

    return 0;
}



F - ABCBAC (abc284 f)

题目大意

给定字符串\(s\)\(n = len(s),i\) ,函数\(f_i(s)\)为以下三个字符串的拼接:

  • \(s[1:i]\)
  • \(s\)的翻转
  • \(s[i+1, n]\)

给定长度为\(2n\)的字符串\(t\),找出一个长度为\(n\)的字符串\(s\)\(i\)满足 \(f_i(s) = t\),或告知不存在。

解题思路

枚举\(i\)\(f_i(s)\)就是由三部分\(p\)组成,剩下的就是判断第一部分\(p_1\)与第二部分 \(p_2\)的对应长度的后半部分是否互为回文串,以及 \(p_3\)\(p_2\)的对应长度的前半部份是否互为回文串。

\(s\prime\)为 串\(s\)的翻转,上述两个条件就是问 \(s\prime\)\(s\)对应子串是否相同,用字符串hash即可在 \(O(1)\)的时间判断。

总的复杂度就是\(O(n)\)

这题还卡了\(1e9+7\)的模数,要换个模数或者双hash.

神奇的代码
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
using ULL = unsigned long long;

#define ENABLE_DOUBLE_HASH

const int x = 135;
const int N = 2e6 + 10;
const int p1 = 1e9 + 7, p2 = 1e9 + 9;
ULL xp1[N], xp2[N], xp[N];

void init_xp() {
    xp1[0] = xp2[0] = xp[0] = 1;
    for (int i = 1; i < N; ++i) {
        xp1[i] = xp1[i - 1] * x % p1;
        xp2[i] = xp2[i - 1] * x % p2;
        xp[i] = xp[i - 1] * x;
    }
}

struct String {
    char s[N];
    int length, subsize;
    bool sorted;
    ULL h[N], hl[N];

    ULL hash() {
        length = strlen(s);
        ULL res1 = 0, res2 = 0;
        h[length] = 0;  // ATTENTION!
        for (int j = length - 1; j >= 0; --j) {
        #ifdef ENABLE_DOUBLE_HASH
            res1 = (res1 * x + s[j]) % p1;
            res2 = (res2 * x + s[j]) % p2;
            h[j] = (res1 << 32) | res2;
        #else
            res1 = res1 * x + s[j];
            h[j] = res1;
        #endif
            // printf("%llu\n", h[j]);
        }
        return h[0];
    }

    // 获取子串哈希,左闭右开区间
    ULL get_substring_hash(int left, int right) const {
        int len = right - left;
    #ifdef ENABLE_DOUBLE_HASH
        // get hash of s[left...right-1]
        unsigned int mask32 = ~(0u);
        ULL left1 = h[left] >> 32, right1 = h[right] >> 32;
        ULL left2 = h[left] & mask32, right2 = h[right] & mask32;
        return (((left1 - right1 * xp1[len] % p1 + p1) % p1) << 32) |
               (((left2 - right2 * xp2[len] % p2 + p2) % p2));
    #else
        return h[left] - h[right] * xp[len];
    #endif
    }

    void init(const char *t) {
        length = strlen(t);
        strcpy(s, t);
    }
};

int main(void) {
    ios::sync_with_stdio(false); 
    cin.tie(0); cout.tie(0);
    init_xp();
    int n;
    string s;
    cin >> n >> s;
    string t = s;
    reverse(t.begin(), t.end());
    String S, T;
    S.init(s.c_str());
    S.hash();
    T.init(t.c_str());
    T.hash();
    auto solve = [&](){
        for(int i = 0; i <= n; ++ i){
            int len1 = n - i;
            int len2 = i;
            if (S.get_substring_hash(i, i + len1) == T.get_substring_hash(0, len1) && 
                S.get_substring_hash(0, len2) == T.get_substring_hash(len1, len1 + len2))
                return i;
        }
        return -1;
    };
    int i = solve();
    if (i == -1)
        cout << i << '\n';
    else {
        cout << t.substr(n - i, n) << '\n' << i << '\n';
    }

    return 0;
}



G - Only Once (abc284 g)

题目大意

对于一个长度为\(n\)的数组 \(A\),其中\(1 \leq a_i \leq n\)。 对于\(1\leq i \leq n\),定义一个长度为\(10^{100}\) 的数组 \(B_i\)

  • \(B_{i,1} = i\)
  • \(B_{i,j + 1} = A_{B_{i, j}} (1 \leq j < 10^{100})\)

\(S_i\)表示 \(B_i\)数组中仅出现一次的数的个数

在所有 \(n^n\)种情况的数组 \(A\)中,求所有\(S_i\)的和,即 \(\sum_{A}\sum_{i=1}^{n} S_i \mod M\)

解题思路

<++>

神奇的代码



Ex - Count Unlabeled Graphs (abc284 h)

题目大意

<++>

解题思路

<++>

神奇的代码



posted @ 2023-01-07 21:47  ~Lanly~  阅读(312)  评论(0编辑  收藏  举报