ICPC2023 陕西邀请赛 题解

G - Permutation

Question

找到一个排列 \(p\),使得 \(\prod_{i=1}^n lcm(p_i,p_{(i mod n) +1})\) 最大

Solution

考虑到 \(x\)\(x-1\) 必然是互质的

所以顺序排列即可

Code

#include<bits/stdc++.h>
using namespace std;
int main() {
    int n; cin >> n;
    for (int i = 1; i <= n; i++)
        cout << i << " ";
    return 0;
}

J - Target

Quesion

给出一个数 \(x(0\le x \le 1)\) ,每次可以对 \(x\) 进行两种操作之一:

  • 1.\(x=x/2\)
  • 2.\(x=(x-1)/x+1\)

需要把 \(x\) 变成 \(y\),认为 \(|x-y| \le 10^{-4}\) 则认为是相同的

输出一种可信的方案

Solution

观察到两个数如果相差小于 \(10^{-4}\) 则是相同的,所以在 \(0\sim 1\) 这个范围内,至多存在 \(10^4\) 个数

直接 \(BFS\),然后判断一个数是否被遍历过即可

如何判断呢?我使用了 \(set\) 来找与一个数最接近的数

Code

#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-5;

int cmp(double x, double y) {
    if (fabs(x - y) < eps) return 0;
    return x < y ? -1 : 1; // x < y 返回 -1, x > y 返回 1
}

set<pair<double, string> > mp;

int main() {
    // freopen ("J.in", "r",stdin);
    double a, b;
    cin >> a >> b;
    queue<double> q; q.push(a);
    mp.insert({a, ""});

    while (!q.empty()) {
        double u = q.front(); q.pop();
        
        auto it = mp.lower_bound({u,""});
        double v = it->first; string s = it->second;

        auto insert = [&] (double nxt_u, string s) {
            if (nxt_u < 0 || nxt_u > 1) return;

            if (cmp(nxt_u, b) == 0) {
                if (s.size() > 50)
                    s = s.substr(0, 50);
                cout << s << endl;
                exit(0);
            }
            
            double v = mp.lower_bound({nxt_u, ""})->first;
            if (cmp(v, nxt_u) == 0) return; // 存在
            mp.insert({nxt_u, s});
            q.push(nxt_u);
        };

        insert(u * 0.5 , s + "1"); 
        insert((u - 1.0) * 0.5 + 1, s + "2");
    }
    return 0;
}

H - Spin the Wheel

Solution

一般形式下的差分数组 \(d[i]=a[i]-a[i-1]\),默认 \(a[0] = 0\)

我们这里定义 \(d[1]=a[1]-a[n]\)

一次 \(2\) 操作是对于差分数组同时 \(+1\)

所以说,如果 \(a\) 的差分数组不是一个值则输出 \(-1\)

否则需要 \(d[i]\)\(2\) 操作

然后考虑旋转,如果不旋转,\(a[0]\) 每次都只能 \(+0\) ,所以 \(a[0]\) 必然为 \(0\)

由于 \(a[0]\)\(0\sim n-1\) 之间,所以需要最后一个把 \(a[0]\) 旋转到 \(0\) 位置即可

也就是说,\(1\) 操作最多进行 \(1\)

特殊考虑差分为 \(0\) 的情况,如果 \(a[0]=0\) 答案是 \(0\),否则答案是 \(n\)

Code

#include <bits/stdc++.h>
using namespace std;
int main() {
    // freopen ("H.in","r",stdin);
    ios::sync_with_stdio(0); cin.tie(0);
    int n; cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++)
        cin >> a[i];
    int ccf = -1;
    for (int i = 0; i < n; i++) {
        int cf = a[i] - a[(i - 1 + n) % n];
        cf = (cf + n) % n;
        if (ccf == -1) ccf = cf;
        else if (ccf != cf) {
            cout << -1 << endl;
            return 0;
        }
    }
    if (a[0] == 0) {
        if (ccf == 0) 
            cout << 0 << endl;
        else 
            cout << ccf << endl;
    }
    else {
        if (ccf == 0)
            cout << n + 1 << endl;
        else
            cout << ccf + 1 << endl;
    }
    return 0;
}
posted @ 2024-03-30 12:52  Martian148  阅读(136)  评论(0编辑  收藏  举报