VP Codeforces Round 889 (Div. 2)


A. Dalton the Teacher

题意:给你一个排列,每次交换两个数,使得\(i \ne p_i\)的最少操作数。

记录\(i = p_i\)的位置个数\(cnt\),答案就是\(\lceil \frac{cnt}{2} \rceil\)

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    	-- a[i];
    }

    int cnt = 0;
    for (int i = 0; i < n; ++ i) {
    	cnt += a[i] == i;
    }
    std::cout << (cnt + 1) / 2 << "\n";
}

B. Longest Divisors Interval

题意:给你一个整数,求一个区间,使得这个区间的所有数都是\(n\)的因子,且区间长度最大。

假设区间是\([l, r]\),那么这些数的因子一定包含了\([1, r - l + 1]\)
那么从小到大枚举即可。

点击查看代码
void solve() {
    i64 n;
    std::cin >> n;
    i64 ans = 1;
    while (n % (ans + 1) == 0) {
    	++ ans;
    }
    std::cout << ans << "\n";
}

C1 && C2. Dual

题意:你要是\(a\)非递减。每次可以选择\(i, j\)使得\(a_i = a_i + a_j\)。求方案,\(C1\)操作数不能超过\(50\)\(C2\)不能超过 \(31\)

如果只有正数或者负数,那么直接前缀和或者后缀和就能满足。
否则我们可以枚举把这些数变成负数还是正数。然后分别前缀和或后缀和。取答案长度最小的。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<i64> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    int pmax = std::max_element(a.begin(), a.end()) - a.begin();
    int pmin = std::min_element(a.begin(), a.end()) - a.begin();
    int max = a[pmax], min = a[pmin];

    if (min >= 0) {
    	std::cout << n - 1 << "\n";
    	for (int i = 1; i < n; ++ i) {
    		std::cout << i + 1 << " " << i << "\n";
    	}
    	return;
    }

    if (max <= 0) {
    	std::cout << n - 1 << "\n";
    	for (int i = n - 2; i >= 0; -- i) {
    		std::cout << i + 1 << " " << i + 2 << "\n";
    	}
    	return;
    }

    std::vector<std::pair<int, int>> ans1;
    std::vector<std::pair<int, int>> ans2;
  	int t = max;
  	while (t < -min) {
  		ans1.emplace_back(pmax, pmax);
  		t *= 2;
  	}  

  	for (int i = 0; i < n; ++ i) {
  		if (a[i] < 0) {
  			ans1.emplace_back(i, pmax);
  		}
  	}

  	for (int i = 1; i < n; ++ i) {
  		ans1.emplace_back(i, i - 1);
  	}
    
    t = min;
    while (-t < max) {
    	ans2.emplace_back(pmin, pmin);
    	t *= 2;
    }

    for (int i = 0; i < n; ++ i) {
    	if (a[i] > 0) {
    		ans2.emplace_back(i, pmin);
    	}
    }

    for (int i = n - 2; i >= 0; -- i) {
    	ans2.emplace_back(i, i + 1);
    }

    auto ans = ans1;
    if (ans2.size() < ans1.size()) {
    	ans = ans2;
    }

    std::cout << ans.size() << "\n";
    for (auto & [i, j] : ans) {
    	std::cout << i + 1 << " " << j + 1 << "\n";
    }
}
posted @ 2025-05-09 18:20  maburb  阅读(16)  评论(0)    收藏  举报