Codeforces Round 948 (Div. 2)(A-D题解)

Codeforces Round 948 (Div. 2)

2024-05-26 —yimg

A

签到题

代码:

#include<bits/stdc++.h>
using namespace std;

void work()
{
	int n, m;
	cin >> n >> m;
	if(n < m){
		cout << "NO\n";
		return;
	}
	if((n - m)&1){
		cout << "NO\n";
		return;
	}
	else{
		cout << "YES\n";
	}
}

int main()
{
	int t;
	cin >> t;
	while(t--)
		work();
}

B

题意:

将一个正整数x进行特殊的二进制分解, 构造出长度为n的数组a,满足

  • 1n32

  • ai=0or1or1 ,0in1

  • x=sumi=0n1ai2i

  •  i[0,n2],ai0 and ai+10

思路:

正常的二进制分解我们很容易做到,可得到一个只含有0和1的数组a,本题多了一个限制条件

,不能有连续非0位,所以我们可以将连续的1位向高位进1,这段1的最低位补-1,值不变

代码:

#include<bits/stdc++.h>
using namespace std;
void work()
{
	int x;
	cin >> x;
	vector<int> a(35);
	int n = __lg(x);
	int cnt = 0;
	while(x){
		a[cnt++] = x&1;
		x >>= 1;
	}
	for(int i = 0; i <= n; ++i){
		if(a[i] == 0) {
			continue;
		}
		else{
			int p = i;
			for(; p <= n; ++p){
				if(a[p] == 0) break;
			}
			if(p == i + 1) continue;
			else{
				a[i] = -1;
				for(int j = i + 1; j < p; ++j)
					a[j] = 0;
				a[p] = 1;
				i = p - 1;
			}
		}
	}
	cout << 32 << '\n';
	for(int i = 0; i < 32; ++i){
		cout << a[i] << ' ';
	}
	cout << '\n';
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while(t--)
		work();
}

C

题意:

给定数组a,为最长特殊子序列能有多长, n2000 and ai109

定义特殊子序列为:此段子序列的lcm在数组a中没有出现过

思路:(枚举)

  • 若原数组的lcm如果大于数组最大值,则答案为n

  • 若原数组的lcm不大于n, 特殊子序列的lcm一定时原数组lcm的因子 ( 因为子lcm 是由 原lcm 去除一些因子得到的 ), 我们可以枚举因子,若此因子没有出现过,并且原数组可以有元素的lcm等于此因子,统计这些元素的个数,取个数的max即为答案, 枚举因子个数可以估算为ai2ai3,时间复杂度为O(nd(ai))

代码:

#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
void work()
{
	int n;
	cin >> n;
	vector<int> a(n);
	for(int i = 0; i < n; ++i)
		cin >> a[i];
	i64 x = 1;
	for(int i = 0; i < n; ++i)
	{
		x = lcm(x, a[i]);
		if(x > 1e9){
			break;
		}
	}
	auto it = find(a.begin(), a.end(), x);
	if(it == a.end()){
		cout << n << '\n';
		return;
	}
	int ans = 0;
	auto check = [&](int d){
		if(find(a.begin(), a.end(), d) != a.end()){
			return;
		}
		int lc = 1;
		int cnt = 0;
		for(int i = 0; i < n; ++i){
			if(d % a[i] == 0){
				cnt++;
				lc = lcm(lc, a[i]);
			}
		}
		if(lc == d){
			ans = max(ans, cnt);
		}
	};
	for(int i = 1; i * i <= x; ++i){
		if(x%i == 0){
			check(i);
			check(x/i);
		}
	}
	cout << ans << '\n';
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while(t--)
		work();
}

D

题意:

给定n * m 的01矩阵, 任意次行xor操作 : 将一整行全部异或1

问特殊列最大能有多少列,并给出操作方案

思路:(枚举, 哈希)

  • 令任意格(i, j) 为1,则此时操作序列一定

  • 枚举每个格子为1时的操作序列, 将操作序列进行哈希, 统计每种操作序列的特殊列数

  • 实现上, 可以令一列全操作为0, 在逐行分别异或为1, 统计最大答案

代码:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
mt19937_64 rnd(time(0));
//mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());
void work()
{
	int n, m;
	cin >> n >> m;
	vector<vector<bool>> table(n, vector<bool>(m));
	for(int i = 0; i < n; ++i)
		for(int j = 0; j < m; ++j){
			char c; cin >> c;
			table[i][j] = c - '0';
		}
	vector<ll> rands(n);
	for(int i = 0; i < n; ++i) rands[i] = rnd();
	map<ll, int> num;
	int res = 0;
	pair<int, int> ans;
	for(int j = 0; j < m; ++j){
		ll summ = 0;
		for(int i = 0; i < n; ++i){
			if(table[i][j]){
				summ ^= rands[i];
			}
		}
		for(int i = 0; i < n; ++i){
			summ ^= rands[i];
			num[summ]++;
			if(res < num[summ]){
				res = num[summ];
				ans = {i, j};
			}
			summ ^= rands[i];
		}
	}
	cout << res << '\n';
	int x = ans.first, y = ans.second;
	for(int i = 0; i < n; ++i){
		if(i == x) cout << (table[i][y] ? 0 : 1);
		else cout << (table[i][y] ? 1 : 0);
	}
	cout << '\n';
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while(t--)
		work();
}
posted @   _yimg  阅读(74)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示