2025牛客暑期多校训练营7


A. Loopy Laggon

题意:\(100\)套玩具,每套有\(k\)个玩具。每一个玩具是一个\(n\times n\)的矩阵。一开始都是从左到右从上到下\(1\)\(n^2\)依次排列。然后进行了很多次操作,每次顺时针旋转一个\(4\times 4\)的子矩阵\(90\)度。然后\(Bob\)过来打乱了\(\frac{m}{2}\)套玩具,每一套的每一个玩具他都打乱了。你需要求出哪套是被打乱过的,哪些没有,需要有\(90%\)的正确率。

把矩阵展成一维,一个性质是不管怎么旋转都不会改变逆序对的奇偶性。
那么如果一套玩具每个矩阵的逆序对都是偶数,我们认为它没被打乱,如果这套玩具是被打乱了,那么逆序对都是偶数的概率是\(2^{-10}\)
否则有一套逆序对是奇数一定是被打乱的。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

template <class T>
struct Fenwick {
    int n;
    std::vector<T> tr;

    Fenwick(int _n) {
        init(_n);
    }

    void init(int _n) {
        n = _n;
        tr.assign(_n + 1, T{});
    }

    void add(int x, const T &v) {
        for (int i = x; i <= n; i += i & -i) {
            tr[i] = tr[i] + v;
        }
    }

    T query(int x) {
        T res{};
        for (int i = x; i; i -= i & -i) {
            res = res + tr[i];
        }
        return res;
    }

    T sum(int l, int r) {
        return query(r) - query(l - 1);
    }
};

int a[100010];
int get(int n) {
	for (int i = 0; i < n * n; ++ i) {
		std::cin >> a[i];
	}

	Fenwick<int> tr(n * n + 1);
	int res = 0;
	for (int i = n * n - 1; i >= 0; -- i) {
		res += tr.query(a[i] - 1);
		tr.add(a[i], 1);
	}
	return res & 1;
}

void solve() {
	int _, m, k, n;
	std::cin >> _ >> m >> k >> n;
	std::string s;
	for (int i = 0; i < m; ++ i) {
		bool flag = false;
		for (int j = 0; j < k; ++ j) {
			flag |= get(n);
		}
		
		if (flag) {
			s += '1';
		} else {
			s += '0';
		}
	}
	std::cout << s << "\n";
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	// std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}

C. Forsaken City

题意:一个数组,每次选择一个子序列都减\(1\)。最少几次操作使得数组不递减。

最后一个位置不操作肯定最优。因为需要前面的都比它小。
那么从后往前模拟,每个数要减到小于等于后面的数。取最大值作为答案。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

void solve() {
	int n;
	std::cin >> n;
	std::vector<int> a(n);
	for (int i = 0; i < n; ++ i) {
		std::cin >> a[i];
	}

	i64 ans = 0;
	for (int i = n - 2; i >= 0; -- i) {
		i64 t = std::max(0, a[i] - a[i + 1]);
		ans = std::max(ans, t);
		a[i] -= t;
	}
	std::cout << ans << "\n";
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}

F. The Correlation

题意:一个数组,每次选择一个\(v\)让所有\(a_i = |a_i - v|\)。求最后两两差的绝对值最小。

每次选择最大值和最小的的平均数最优。这样最大值每次减一半,大概操作\(log_V\)次。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

const int mod = 998244353;

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

	for (int t = 1; t <= n; ++ t) {
		i64 sum = std::ranges::max(a) + std::ranges::min(a) >> 1;
		if (sum <= 0) {
			break;
		}
		for (int i = 0; i < n; ++ i) {
			a[i] = std::abs(a[i] - sum);
		}
	}


	std::ranges::sort(a);
	i64 ans = 0;
	for (int i = 0; i < n; ++ i) {
		ans = (ans + ((i64)(n - i - 1) * -a[i] % mod + mod) % mod) % mod;
		ans = (ans + (i64)i * a[i] % mod) % mod;
	}
	std::cout << ans << "\n";
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	// std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}

G. Nice Doppelgnger

题意:从\([1, n]\)里选\(\frac{n}{2}\)个数。满足任意三个数(可以重复选一个数)的乘积不是平方数。

平方数的每个质因子的幂都是偶数。
一个数有奇数个幂是奇数的质因子,我们就选它。也就是\(p_1^{2k_1 + 1}p_2^{2k_2 + 1}...p_n^{2k_n + 1},(n是奇数)\)这种乘上若干个其它质数的偶数幂。打表发现个数够的。可以欧拉筛预处理最小质因子后,每个数\(log\)的时间检验。
手玩发现,这样选出的数任意三个都无法把所有奇数幂的质因子的幂变成偶数。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

std::vector<int> primes, minp, st;

void sieve(int n) {
	minp.assign(n + 1, 0);
	st.assign(n + 1, 0);
	for (int i = 2; i <= n; ++ i) {
		if (minp[i] == 0) {
			minp[i] = i;
			primes.push_back(i);
		}

		for (auto & p : primes) {
			if (p * i > n) {
				break;
			}

			minp[p * i] = p;
			if (minp[i] == p) {
				break;
			}
		}
	}

	for (int i = 2; i <= n; ++ i) {
		int cnt = 0;
		int x = i;
		while (x > 1) {
			int p = minp[x];
			int cnt1 = 0;
			while (x % p == 0) {
				x /= p;
				++ cnt1;
			}

			cnt += cnt1 & 1;
		}

		if (cnt & 1) {
			st[i] = 1;
		}
	}
}

void solve() {
	int n;
	std::cin >> n;
	std::vector<i64> a;
	for (int i = 2; i <= n; ++ i) {
		if (st[i]) {
			a.push_back(i);
		}

		if (a.size() >= n / 2) {
			break;
		}
	}

	for (auto & x : a) {
		std::cout << x << " \n"[x == a.back()];
	}
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	sieve(2e6);
	std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}

J. Ivory

题意:求\(gcd(a^b, c^d)\)

\(g=gcd(a,b)\)。如果\(g\leq 10^9\),直接暴力分解质因数,对于每个质数\(p\)\(a\)中有\(x\)个,\(c\)中有\(y\)个,那么\(gcd\)里有\(min(xb, yd)\)个。
如果\(g\geq 10^9\),记\(x = \frac{a}{g}, y = \frac{c}{g}\),这里令\(b<d\),那么式子变成\(gcd(x^bg^b, y^dg^d) = g^bgcd(x^b, g^{d-b})\),递归计算即可。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;
using i128 = __int128;

const int mod = 998244353;

i64 power(i64 a, i128 b) {
    a %= mod;
    i64 res = 1;
    for (;b;b >>= 1, a = a * a % mod) {
        if (b & 1) {
            res = res * a % mod;
        }
    }

    return res;
}

std::vector<int> primes, minp;

void sieve(int n) {
    minp.assign(n + 1, 0);
    for (int i = 2; i <= n; ++ i) {
        if (minp[i] == 0) {
            minp[i] = i;
            primes.push_back(i);
        }

        for (auto & p : primes) {
            if (p * i > n) {
                break;
            }

            minp[p * i] = p;
            if (minp[i] == p) {
                break;
            }
        }
    }
}

i128 get(i64 a, i64 p) {
    int res = 0;
    while (a % p == 0) {
        ++ res;
        a /= p;
    }
    return res;
}

i64 f(i64 a, i64 b, i64 c, i64 d) {
    if (b > d) {
        std::swap(a, c);
        std::swap(b, d);
    }

    i64 g = std::gcd(a, c);
    if (g <= 2e7) {
        i64 res = 1;
        while (g > 1) {
            int p = minp[g];
            while (g % p == 0) {
                g /= p;
            }

            res = res * power(p, std::min(get(a, p) * b, get(c, p) * d)) % mod;
        }
        return res;
    }

    return power(g, b) * f(a / g, b, g, d - b) % mod;
}

void solve() {
    i64 a, b, c, d;
    std::cin >> a >> b >> c >> d;
    std::cout << f(a, b, c, d) << "\n";
}

int main() {
    std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    int t = 1;
    sieve(2e7);
    std::cin >> t;
    while (t -- ) {
        solve();
    }
    return 0;
}
posted @ 2025-08-06 12:27  maburb  阅读(82)  评论(2)    收藏  举报