Codeforces Round 1091 (Div. 2) and CodeCraft 26

文章目录

  • [B&D 思维 问题转化](#B&D 思维 问题转化)
  • [C 数论 同余](#C 数论 同余)

原题链接

B&D 思维 问题转化

B题k=1

连续的可以统一处理 化成一个数

把x化成0 要去掉的数就是1

发现消掉一个1 需要两步 也可以两边同时消掉也是两步

cpp 复制代码
void solve()
{
	int n, k;
	cin >> n >> k;
	vector<int> a(n + 1);
	a[0] = -1;
	int p;
	forr(i, 1, n) cin >> a[i];
	cin >> p;
	int x = a[p];
	int fg = 1;
	forr(i, 1, n) if (a[i] != a[p])
	{
		fg = 0;
		break;
	}
	if (fg)
		return cout << 0 << endl, void();
	vector<int> b;
	b.push_back(0);
	int np = 0;
	forr(i, 1, n)
	{
		if (a[i] != a[i - 1]) // 连续的可以统一处理
			b.push_back(a[i] ^ x);
		if (i == p)
			np = b.size() - 1;
	}
	p = np;
	n = b.size() - 1;
	int lcnt = 0, rcnt = 0;
	reforr(i, 1, p - 1) if (b[i] == 1) lcnt++;
	forr(i, p + 1, n) if (b[i] == 1) rcnt++;
	/*
		每次消掉一个1 需要2次操作 eg.01
		可以两边配对消掉 cost=2*(max(lcnt, rcnt)-min(lcnt, rcnt))+2*min(lcnt, rcnt)=2 * max(lcnt, rcnt)
	*/
	cout << 2 * max(lcnt, rcnt) << endl;
}

D k>=1

用包含special index的区间把两边的1消掉,可以把special index看作区段端点,去掉区段中的1

cpp 复制代码
void solve()
{
	int n, k;
	cin >> n >> k;
	vector<int> a(n + 1), p(k + 1);
	a[0] = -1;

	forr(i, 1, n) cin >> a[i];
	forr(i, 1, k) cin >> p[i];
	int x = a[p[1]];
	int fg = 1;
	forr(i, 1, n) if (a[i] != x)
	{
		fg = 0;
		break;
	}
	if (fg)
		return cout << 0 << endl, void();

	vector<int> b;
	b.push_back(-1);
	int id = 1;
	vector<int> np;
	forr(i, 1, n)
	{
		if (a[i] != a[i - 1]) // 连续的可以统一处理
			b.push_back(a[i] ^ x);
		if (id <= k && i == p[id])
		{
			np.push_back(b.size() - 1);
			id++;
		}
	}
	np.erase(unique(np.begin(), np.end()), np.end());
	n = b.size() - 1;

	np.push_back(n);
	vector<int> preb(n + 1, 0);
	forr(i, 1, n) preb[i] = preb[i - 1] + b[i];
	/*
	目标:消掉每个special index之间的1 就是让每个seg_i=0
	op1:一个/两个位置seg_i -1代价为2
	op2:三个位置seg_i -1 代价为3

	mx<=sm-mx 只用op1就能消掉:mx和sm-mx两两消掉 剩下sm-2*mx
		- sm偶数 cost=mx*2+2*(sm-2*mx)/2=sm
		- sm及数 如果用op2 sm-3=2k 改变奇偶性cost=mx*2+2*(sm-3-2*mx)/2+3=sm
	mx>sm-mx 只用op1
		两两消掉后 mx剩下mx-(sm-mx)=2mx-sm而且只在一个位置
		cost=2*(sm-mx)+2*(2*mx-sm)=2*mx

	*/
	vector<int> segb;
	forr(i, 0, np.size() - 1)
	{
		if (i == 0)
			segb.push_back(preb[np[i]]);
		else
			segb.push_back(preb[np[i]] - preb[np[i - 1]]);
	}
	int sm = 0, mx = 0;
	for (auto i : segb)
		sm += i, mx = max(mx, i);
	// cout << sm << ' ' << mx << endl;
	if (mx * 2 > sm)
		cout << 2 * mx << endl;
	else
		cout << sm << endl;

	// int lcnt = 0, rcnt = 0;
	// reforr(i, 1, p - 1) if (b[i] == 1) lcnt++;
	// forr(i, p + 1, n) if (b[i] == 1) rcnt++;
	// /*
	// 	每次消掉一个1 需要2次操作 eg.01
	// 	可以两边配对消掉
	// */
	// // cout << lcnt << ' ' << rcnt << endl;
	// cout << 2 * max(lcnt, rcnt) << endl;
}

C 数论 同余


参考@ImALAS 的题解

dalao写的太好了,谢谢大佬

cpp 复制代码
void solve()
{
  int n, m, a, b;
  cin >> n >> m >> a >> b;
  if ((__gcd(n, a) == 1 && __gcd(m, b) == 1) && __gcd(n, m) <= 2)
    yes;
  /*

    走偶数步走到原来格子
      x轮 n|ax=>n|x m|bx=>m|x lcm(n,m)|x
      gcd(n,m)=1
      x_max=n*m
    gcd(n,m)=2 奇数步不会走到原来格子 会遍历完
  */
  else
    no;
}
相关推荐
H Journey1 小时前
常用知识总结C++、CMake、Linux
linux·c++·opencv·cmake
凌波粒1 小时前
LeetCode--二叉树前中后序遍历的递归与迭代实现(二叉树/DFS)
算法·leetcode·深度优先
啊哦呃咦唔鱼1 小时前
Leetcodehot100-215. 数组中的第K个最大元素
数据结构·算法·leetcode
cany10002 小时前
C++ -- 宏和模板
开发语言·c++
老赵聊算法、大模型备案2 小时前
从剪映、即梦 AI 被罚,读懂 AI 生成内容标识硬性合规要求
人工智能·算法·安全·aigc
shehuiyuelaiyuehao2 小时前
算法12,滑动窗口,将x减到0的最小操作数
java·数据结构·算法
6Hzlia2 小时前
【Hot 100 刷题计划】 LeetCode 19. 删除链表的倒数第 N 个结点 | C++ 双指针单趟遍历
c++·leetcode·链表
_深海凉_2 小时前
LeetCode热题100-跳跃游戏 II
算法·leetcode·游戏
csuzhucong2 小时前
力扣OJ(2301-2600)
算法·leetcode·职场和发展