Loading

The 2024 ICPC Kunming Invitational Contest



A - Two-star Contest

题意

思路

答奋题,贴队友的代码

代码

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define endl '\n';
#define inf 1e18
using namespace std;

struct node {
	int i;
	int s = 0;
	int sum = 0, cnt = 0;
	queue<int> q;
	friend bool operator > (node n1, node n2) {
		return n1.s > n2.s;
	}
};
void solve() {
	int n, m, k;
	cin >> n >> m >> k;
	vector<vector<int> > t(n + 1, vector<int>(m + 1));
	vector<node> ord(n + 1);
	vector<int> c(n + 1);
	for (int i = 1; i <= n; ++i) {
		cin >> ord[i].s;
		ord[i].i = i;
		c[i] = ord[i].s;
		for (int j = 1; j <= m; ++j) {
			cin >> t[i][j];
			if (t[i][j] == -1) ord[i].cnt++;
			else ord[i].sum += t[i][j];
		}
	}
	sort(c.begin(), c.end());
	for (int i = 1; i <= n; ++i) {
		ord[i].s = lower_bound(c.begin(), c.end(), ord[i].s) - c.begin();
	}
	vector<node> d[n + 1];
	for (int i = 1; i <= n; ++i) {
		d[ord[i].s].push_back(ord[i]);
	}
	int lim = inf;
	for (int i = n; i; --i) {
		int res = inf;
		if (!d[i].size()) continue;
		for (auto nn : d[i]) {
			if (nn.sum >= lim) {
				cout << "No" << endl;
				return;
			}
			for (int j = 1; j <= nn.cnt; ++j) {
				if (nn.sum + k < lim) {
					nn.sum += k;
					ord[nn.i].q.push(k);
				}
				else {
					ord[nn.i].q.push(lim - nn.sum - 1);
					nn.sum += lim - nn.sum - 1;
				}
			}
			res = min(res, nn.sum);
		}
		lim = res;
	}
	cout << "Yes" << endl;
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= m; ++j) {
			if (t[i][j] != -1) cout << t[i][j] << ' ';
			else {
				cout << ord[i].q.front() << ' ';
				ord[i].q.pop();
			}
		}
		cout << endl;
	}
};

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

	return 0;
}

B - Gold Medal

题意

思路

\(a_i\)补成\(k\)的倍数,每次取补的最少的加到答案(要补的一样,先取大的和先取小的无所谓),同时减少\(m\),不够补就直接加。最后如果\(m\)有剩还要加\(\lfloor {\frac m k} \rfloor\)

代码

点击查看代码
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
using namespace std;
#define int long long
#define endl '\n'
typedef pair<int, int> pii;

const int mxn = 2e5 + 10;

void solve()
{
    int n, k, m;
    cin >> n >> k;
    vector<pii> a(n);
    for (int i = 0; i < n; i++)
    {
        cin >> a[i].second;
        a[i].first = k - a[i].second % k;
    }
    cin >> m;
    sort(a.begin(), a.end());
    int ans = 0;
    for (int i = 0; i < n; i++)
    {
        if (m - a[i].first >= 0)
        {
            ans += (a[i].first + a[i].second) / k;
            m -= a[i].first;
        }
        else
        {
            ans += (a[i].second + m) / k;
            m = 0;
        }
    }
    ans += m / k;
    cout << ans << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);

    int __ = 1;
    cin >> __;
    while (__--)
    {
        solve();
    }

    return 0;
}

E - Relearn through Review

题意

思路

维护原数组的前缀\(gcd\)和后缀\(gcd\),枚举区间并加上\(k\),当前\(gcd\)就是前缀\(gcd\)、后缀\(gcd\)和当前区间\(gcd\)\(gcd\)。此时还是\(O(n^2)\),由于前缀\(gcd\)不会增大,只有在减小的时候会改变当前\(gcd\),所以\(gcd\)相同的部分可以跳过

代码

点击查看代码
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
using namespace std;
#define int long long
#define endl '\n'
typedef pair<int, int> pii;

const int mxn = 2e5 + 10;

void solve()
{
    int n, k;
    cin >> n >> k;
    vector<int> a(n);
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
    vector<int> pre(n), suf(n);
    pre[0] = a[0];
    for (int i = 1; i < n; i++)
    {
        pre[i] = gcd(pre[i - 1], a[i]);
    }
    suf[n - 1] = a[n - 1];
    for (int i = n - 2; i >= 0; i--)
    {
        suf[i] = gcd(suf[i + 1], a[i]);
    }
    int ans = pre[n - 1];
    for (int i = 0; i < n; i++)
    {
        if (i && pre[i] == pre[i - 1])
        {
            continue;
        }
        int t = pre[max(0LL, i - 1)];
        for (int j = i; j < n; j++)
        {
            if (j == 0)
            {
                t = a[j] + k;
            }
            else
            {
                t = gcd(t, a[j] + k);
            }
            if (j != n - 1)
            {
                ans = max(ans, gcd(t, suf[j + 1]));
            }
        }
        ans = max(ans, t);
    }
    cout << ans << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);

    int __ = 1;
    cin >> __;
    while (__--)
    {
        solve();
    }

    return 0;
}

G - Be Positive

题意

思路一

\(n =1\)\(n\ mod\ 4=0\) 都不行,因为所有数异或起来就是0。其他按\(4\)个一组,交换相邻两组元素即是最小字典序

代码一

点击查看代码
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
using namespace std;
#define int long long
#define endl '\n'
typedef pair<int, int> pii;

const int mxn = 2e5 + 10;

void solve()
{
	int n;
	cin >> n;
	if (n == 1 || n % 4 == 0)
	{
		cout << "impossible" << endl;
		return;
	}
	vector<int> a(n);
	iota(a.begin(), a.end(), 0);
	swap(a[0], a[1]);
	for (int i = 3; i < n; i += 4)
	{
		swap(a[i], a[i + 1]);
	}
	for (auto& i : a)
	{
		cout << i << " ";
	}
	cout << endl;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	int __ = 1;
	cin >> __;
	while (__--)
	{
		solve();
	}

	return 0;
}

思路二

代码二

点击查看代码
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
using namespace std;
#define int long long
#define endl '\n'

const int mxn = 1e6 + 10;

bool sta[mxn];

void init()
{
	vector<int> sum(31);
	for (int i = 0; i < mxn; i++)
	{
		int x = i, cnt = 1;
		while (x)
		{
			sum[cnt] += x & 1;
			cnt++;
			x >>= 1;
		}
		for (int j = 0; j < 31; j++)
		{
			if (sum[j] & 1)
			{
				sta[i] = true;
				break;
			}
		}
	}
}

void solve()
{
	int n;
	cin >> n;
	if (!sta[n - 1])
	{
		cout << "impossible" << endl;
		return;
	}
	for (int i = 0; i < n; i++)
	{
		if (!sta[i])
		{
			cout << i + 1;
		}
		else if (i && !sta[i - 1])
		{
			cout << i - 1;
		}
		else
		{
			cout << i;
		}
		cout << " ";
	}
	cout << endl;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	init();
	int __ = 1;
	cin >> __;
	while (__--)
	{
		solve();
	}

	return 0;
}

I - Left Shifting 2

题意

思路

可以看出一个字符相同的子串的贡献是\(\lfloor {\frac n 2} \rfloor\)(\(n\)为子串长度);而对于左移操作,只有将偶数长度的子串的一个字符移到开头,其他在结尾才能减少\(1\)的操作数。因此要考虑是否有偶数长度的子串以及这个子串是否能被“隔开”,只有两个条件都满足才能减少\(1\)的操作数

代码

点击查看代码
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
using namespace std;
#define int long long
#define endl '\n'
typedef pair<int, int> pii;

const int mxn = 2e5 + 10;

void solve()
{
    string s;
    cin >> s;
    int ans = 0;
    unordered_set<char> st;
    bool even = false, div = false;
    for (auto& i : s)
    {
        st.insert(i);
    }
    int cnt = 0;
    if ((int)st.size() > 1)
    {
        div = true;
        // 排除首尾相同且是偶数长度的情况
        while (s.back() == s[cnt])
        {
            s.push_back(s[cnt]);
            cnt++;
        }
    }
    s.push_back('%');
    for (int i = cnt; i < (int)s.size();)
    {
        int p = i;
        while (s[++p] == s[i]);
        ans += (p - i) >> 1;
        if ((p - i) % 2 == 0)
        {
            even = true;
        }
        i = p;
    }
    cout << ans - (even && div) << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);

    int __ = 1;
    cin >> __;
    while (__--)
    {
        solve();
    }

    return 0;
}


比赛链接 https://codeforces.com/gym/105386

posted @ 2025-03-26 22:06  _SeiI  阅读(262)  评论(0)    收藏  举报