Contestant. Rank 3808. Rating +17.

A. Exponential Equation

题意

给定整数 \(n\),输出一对 \(x, y\),满足 \(x ^ y \cdot y + y ^ x \cdot x = n\)

思路

不妨令 \(x = 1\),那么 \(y = n / 2\)

显然,当 \(n\) 为奇数的时候,一定是无解的,因为 \(x ^ y \cdot y\)\(y ^ x \cdot x\) 的奇偶性一定是一致的。

所以,\(n\) 为偶数的时候,输出 \(1, n / 2\)

时间复杂度:\(O(1)\)

对应AC代码

import java.math.BigInteger;
import java.util.*;

public class Main{

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int t = scanner.nextInt();
        nxt:
        while (t-- > 0) {
            int n = scanner.nextInt();
            if(n % 2 == 1) System.out.println(-1);
            else System.out.printf("%d %d\n", 1, n / 2);
        }
    }

}

你说我怎么就这么蠢

B. Number Factorization

题意

给定一个整数 \(n\),构建数组 \(a, p\),使 \(n = \prod a_i^{p_i}\)。其中,\(a_i\) 必须为不相同的质数的乘积。

输出 \(\sum a_i \cdot p_i\) 的最大值。

思路

显然,\(a_i ^ {p_i} = a_i \cdot a_i \cdot \ldots\),那么我们不妨直接拆开,令所有 \(p_i = 1\)

那么,我们只需分解质因数,分别将出现次数 \(\geq 1\) 次、\(\geq 2\) 次 ... 的数相乘后求和即可。

时间复杂度:不会分析

对应AC代码

#include <bits/stdc++.h>

using namespace std;

const int N = 500010, inf = 0x3f3f3f3f;

#define int long long

vector<int> primes;
bool vis[N];

void init() {
    for (int i = 2; i <= N; ++i) {
        if (!vis[i]) {
            primes.emplace_back(i);
        }
        for (int j : primes) {
            if (1ll * i * j > N) break;
            vis[i * j] = true;
            if (i % j == 0) break;
        }
    }
}

vector<tuple<int, int, bool>> fact(int x) {
    vector<tuple<int, int, bool>> f;
    for (int i : primes) {
        if(i > x) break;
        if (x % i == 0) {
            int cnt = 0;
            while (x % i == 0) x /= i, cnt ++;
            if(cnt != 0) f.emplace_back(i, cnt, false);
        }
    }
    if (x != 1) {
        f.emplace_back(x, 1, false);
    }
    return f;
}

signed main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    init();
    int t, n;
    cin >> t;
    while(t --) {
        cin >> n;
        vector<tuple<int, int, bool>> f = fact(n);
        int ans = 0, cnt = f.size();
        while(cnt > 0){
            int now = 1;
            for(auto &e : f){
                int x, p, ok;
                tie(x, p, ok) = e;
                if(ok) continue;
                now *= x;
                p --;
                if(p == 0) get<2>(e) = true, cnt --;
                get<1>(e) = p;
            }
            ans += now;
        }
        cout << ans << '\n';
    }
}

写得好乱

C. Remove the Bracket

题意

给定一个数组 \(a\) 以及一个整数 \(s\),对于所有 \(i \in [2, n- 1]\),有 \(x_i+y_i=a_i\)\((x_i - s)(y_i - s) \geq 0\)

构造 \(x_i, y_i\),让下列式子的值最小,并输出这个值

\(F = a_1 \cdot x_2+y_2 \cdot x_3+y_3 \cdot x_4 + \ldots + y_{n - 2} \cdot x_{n-1}+y_{n-1} \cdot a_n\)

思路

我们不妨来单独考虑 \(x_i,y_i\)

将其放入式子,我们可以得到 \(\ldots+ y_{i-1}\cdot x_i+y_i\cdot x_{i+1}+\ldots\)。在这段式子里,若 \(x_i + 1,y_i - 1\),那么整个式子将会减少 \(x_{i + 1} - y_{i - 1}\)

也就是说,我们希望 \(x_i\)\(y_i\) 取到 \(s\),因为只有在边界才能找到最值。

因而,我们可以用 \(dp\) 枚举所有我们希望的情况中的最小值。

时间复杂度:\(O(n)\)

对应AC代码

import java.io.*;
import java.math.*;
import java.util.*;
import java.util.concurrent.atomic.*;

public class Main{

    public static void main(String[] args) throws Exception{
        Console console = new Console();
        int t = console.nextInt();
        nxt:
        while(t -- > 0){
            int n = console.nextInt(), s = console.nextInt();
            long[] min = new long[n + 1], max = new long[n + 1];
            for(int i=1;i<=n;i++){
                int cur = console.nextInt();
                if(i == 1 || i == n){
                    min[i] = max[i] = cur;
                }else if(cur <= s){
                    min[i] = 0;
                    max[i] = cur;
                }else{
                    min[i] = Math.min(s, cur - s);
                    max[i] = Math.max(s, cur - s);
                }
            }
            long[][] dp = new long[n + 1][2];
            for(int i=2;i<=n;i++){
                dp[i][0] = Math.min(dp[i - 1][0] + max[i - 1] * min[i], dp[i - 1][1] + min[i - 1] * min[i]);
                dp[i][1] = Math.min(dp[i - 1][0] + max[i - 1] * max[i], dp[i - 1][1] + min[i - 1] * max[i]);
            }
            console.println(dp[n][0]);
        }
        console.close();
    }

    //快读模板 此处略去
    //public static class Console implements Closeable {}

}

论想不到dp于是乱找规律这件事