2023.1.7(Atcoder Beginner Contest 284)

A.Happy New Year 2023

https://atcoder.jp/contests/abc284/tasks/abc284_d

Statement

将给定的 \(N\) 分解成 \(N = p ^ 2 \cdot q\) 的形式,其中 \(p, q\) 为两个不相同的质数 \((1 \leq N \leq 9 \cdot 10 ^{18})\)

Solution

由于 \(N\) 很大,可以使用时间复杂度较优的 Pollard’s rho 算法。

也可以观察到,\(min(p, q)\)\(\sqrt[3]{n}\) 级别的。因此我们可以枚举这个值 \(x\),判断它是否可以作为 \(p\)\(q\)。 可以作为 \(p\) 的条件是 \(n \% (x * x) =0\) ,可以作为 \(q\) 的条件是 \(n \% x = 0\)\(\frac {n} {x}\) 是完全平方数。

Code

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;

int T;
ll n;

bool issquare(ll x) { return (ll)sqrt(x) == sqrt(x); }

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    freopen("in","r", stdin);
    cin >> T;
    while (T--) {
        cin >> n;
        for (ll i = 2; i * i * i <= n; i++) {
            if (n % i == 0 && issquare(n / i)) {
                cout << (ll)sqrt(n / i) << " " << i << endl;
                break;
            }
            if (n % (i * i) == 0) {
                cout << i << " " << n / i / i << endl;
                break;
            }
        }
    }
	return 0;
}

B.Count Simple Paths

https://atcoder.jp/contests/abc284/tasks/abc284_e

Statement

给定一个 \(n\) 个点 \(m\) 条边的无向图,保证每个点的度数在 \(10\) 以内,求出从 \(1\) 号节点为起点的所有简单路径的个数。(若个数大于 \(10^6\) 则输出 \(10^6\))。

Solution

朴素想法是直接对图进行dfs遍历。关键点是题目中对于度数的限制。有了这个限制,可以保证“在搜索的过程中不会因为进入一个不优的节点而需要耗费相当多的代价再走回来”。因此时间复杂度是正确的。

C.ABCBAC

https://atcoder.jp/contests/abc284/tasks/abc284_f

Statement

对于一个长度为 \(n\) 的字符串 \(S\),通过\(f_i(S)\) 构造出一个长度为 \(2n\) 的字符串 \(T\)

\(f_i(S)\)\(S\) 的前 \(i\) 个字母 + \(S\) 的倒序字符串 + \(S\)的后 \(n - i\) 个字母。

现给出 \(n\)\(T\),询问是否能得到一组可行的 \(S\)\(i\)。有解则输出方案。

Solution

枚举 \(i\),同时结合字符串双哈希即可。

Code

#include <bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
const int N = 2e6 + 5;
typedef long long ll;
using namespace std;

int n;
string t;

//Double Hash Model
typedef pair<int, int> Hash;
const ll mod1 = 1e9 + 7;
const ll mod2 = 1e9 + 9;

Hash operator + (Hash a, Hash b) {
    int c1 = a.fi + b.fi, c2 = a.se + b.se;
    if (c1 >= mod1) c1 -= mod1;
    if (c2 >= mod2) c2 -= mod2;
    return mp(c1, c2);
}

Hash operator - (Hash a, Hash b) {
    int c1 = a.fi - b.fi, c2 = a.se - b.se;
    if (c1 < 0) c1 += mod1;
    if (c2 < 0) c2 += mod2;
    return mp(c1, c2);
}

Hash operator * (Hash a, Hash b) {
    int c1 = 1ll * a.fi * b.fi % mod1, c2 = 1ll * a.se * b.se % mod2;
    return mp(c1, c2);
}

Hash pw[N], pre[N], suf[N];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    freopen("in","r", stdin);
    cin >> n >> t;
    n *= 2;
    Hash base = mp(13331, 23333);
    pw[0] = mp(1, 1);
    for (int i = 1; i <= n; i++) {
        pw[i] = pw[i - 1] * base;
        pre[i] = pre[i - 1] * base + mp(t[i - 1], t[i - 1]);
    }
    for (int i = n; i >= 1; i--) suf[i] = suf[i + 1] * base + mp(t[i - 1], t[i - 1]);
    for (int i = 0; i <= n / 2; i++) {
        Hash res1 = (pre[i] * pw[n / 2 - i]) + (pre[n] - pre[i + n / 2] * pw[n / 2 - i]);
        Hash res2 = suf[i + 1] - suf[i + 1 + n / 2] * pw[n / 2];
        if (res1 == res2) {
            cout << t.substr(0, i) + t.substr(i + n / 2, n - i) << endl;
            cout << i << endl;
            return 0;
        }
    }
    cout << "-1" << endl;
	return 0;
}

posted @ 2023-01-08 01:49  BeyondLimits  阅读(132)  评论(0编辑  收藏  举报