首页 > 其他分享 >Codeforces Round 910 (Div. 2)

Codeforces Round 910 (Div. 2)

时间:2023-11-20 10:23:22浏览次数:34  
标签:temp int Codeforces long li ans Div include 910

Codeforces Round 910 (Div. 2)

基本情况

做A题的速度比之前快多了,大概20分钟搞定。

B题想了一个贪心错解,想用链表实现,但是不熟练,实现太慢,而且还被hack了。

但是自己hack掉了,造数据上进步。

B. Milena and Admirer

贪心思路

发现一个大于下一个的数,直接对半分,如果不能对半就小的在前大的在后。

分完之后用链表先删除当前数,再插入两个新的数,然后再跑一次新的数列。

代码实现

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <list>

using namespace std;

int n;
list<long long> a;
long long temp;

void solve()
{
	long long ans = 0;
	while (true)
	{
		int cnt = 0;
		auto tp = a.begin();
		long long temp = *tp;
		tp++;
		for (auto p = tp; p != a.end(); p++)
		{
			if (*p > temp)
			{
				temp = *p;
				if (temp % 2 == 0)
				{
					p = a.erase(p);
					p = a.insert(p, {temp / 2, temp / 2});
				}
				else
				{
					p = a.erase(p);
					p = a.insert(p, {temp - temp / 2, temp / 2});
				}
				cnt++;
			}
			else
			{
				temp = *p;
			}
		}
		ans += cnt;
		if (cnt == 0)
		{
			break;
		}
	}
	cout << ans << endl;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	int T;
	cin >> T;
	while (T--)
	{
		a.clear();
		cin >> n;
		for (int i = 1; i <= n; i++)
		{
			cin >> temp;
			a.push_front(temp);
		}
		solve();
	}
	return 0;
}

光是实现这个错解就满头大汗了。

因为指针操作不熟练,一开始我对删除加入新元素的操作是这样实现的

a.erase(p);
a.insert(p, {temp / 2, temp / 2});

然后导致各种异常,因为第一个操作过后\(p\)指针指向的东西都被删除了,不能直接\(p\)那边插入,这跟数组下标不一样。而是通过这类函数都会返回的操作完的指针位置来定位下一步操作的指针位置。

p = a.erase(p);
p = a.insert(p, {temp / 2, temp / 2});

HACK

然而这是错解。

我发现了一组数据

3
2 6 2

这组数据如果按照我的解法

2 6 2\\0
2 3 3 2\\1
2 1 2 1 2 2\\3
1 1 1 1 1 1 2 2\\5

而最优解却是

2 6 2\\0
2 2 4 2\\1
2 2 2 2 2\\2

然而只剩5分钟结束了。

正确贪心

思路

正解是贪心没错。

目标性更强,当发现一个大于后面元素的数之后,操作的目的是让这个数变得尽可能等于后面那个数。

即\(\lceil \frac{a_{i-1}}{k} \rceil \leq a_i\)

变换一下,就是找出 \(k=\lceil \frac{a_{i-1}}{a_i} \rceil\)

那么答案加上 \(k - 1\),因为分成 \(k\) 分 只要操作 \(k-1\) 次。

然后把当前这个数设置为 \(\lfloor \frac{a_{i-1}}{k} \rfloor\) ,即均分为\(k\)个之后的最小部分,来保证之后算法的正确性。

用这个算法来操作刚才的 hack 数据。

2 6 2\\0
6 / 2 = 3
ans += 3 - 1;
2 2 2\\2

确实正确。

实现

然而实现也没那么舒服,我一开始没有彻底理解这个做法,导致答案始终出错。

这是一开始的代码

for (int i = 2; i <= n; i++)
{
	int k = getUpper(a[i - 1], a[i]); 
	ans += k - 1;
	a[i - 1] /= k;
}

问题在于,我的\(a[i - 1]\)是为了保证之后答案的正确性才取了分割后的最小部分,但是顺着枚举下一次根本用不到\(a[i - 1]\),顺序改一下就过了。

#include<iostream>
#include<algorithm>
#include<cstdio>

using namespace std;
using li = long int;

const int N = 2e5 + 10;
li a[N],n; 

li getUpper(li a, li b)
{
	if (a % b == 0)
	{
		return a / b;
	} else {
		return a / b + 1;
	}
}

int main()
{
	int T;
	li ans;
	cin >> T;
	while(T--)
	{
		cin >> n;
		ans = 0;
		for (int i = 1; i <= n; i++)cin >> a[i];
		for (int i = n - 1; i >= 1; i--)
		{
			int k = getUpper(a[i], a[i + 1]); 
			ans += k - 1;
			a[i] /= k;
		}
		cout << ans << endl;
	}
	return 0;
}

标签:temp,int,Codeforces,long,li,ans,Div,include,910
From: https://www.cnblogs.com/kdlyh/p/17843354.html

相关文章

  • Codeforces Round 909 (Div. 3)
    CodeforcesRound909(Div.3)基本情况第一次在CF上AC了超过一道题。(毕竟是Div3)B题卡住了很久。D没有深入思考。[B.250ThousandTonsofTNT](Problem-B-Codeforces)一开始死活过不了的代码:#include<iostream>#include<cstdio>#include<cstring>#inc......
  • CF909 div3
    CF909div3A.GamewithIntegers题意两人博弈,给出一个数字,每人每次可以选择令该数字+1或者-1。如果在10步以内可以令数字为3的倍数,先手胜。否则后手胜。数据范围多组数据,\(1<=T<=100,1<=n<=1000\)题解后手可以恢复现场,所以先手最多只能有效操作1次。若+1或者-1......
  • Educational Codeforces Round 13 E
    tilian最开始看错了以为是可以任意选择两人or选择一人胜出但题意是可以选择下一个擂主是谁考虑dp的话我们显然需要记录一个state以及当前擂主是谁转移就是dp[state][i]=max(dp[state][i],dp[state(1<<j)][j]*a[i][j]+dp[state(1<<i)]*a[j][i])意义是我们枚举他后一个交......
  • Codeforces Round 909 (Div. 3) A-E
    CodeforcesRound909(Div.3)A.GamewithIntegers题意:两人轮流操作,可以加一或减一,若结果能被3整除则输出First,否则输出Second思路:若n不能被3整除,则第一个人可以直接通过加一或减一使结果被3整除,反之则一定不能代码:#include<bits/stdc++.h>usingnamespacestd;cons......
  • cf1864C. Divisor Chain
    https://codeforces.com/contest/1864/problem/C思维越来越僵化了假如\(n=2^k\),直接每次/2就行。否则,我们可以考虑如何转化成上面的情况令\(n=2^kx\),那么我们显然可以转移到\(n=2^k(x-1)\),因为x是奇数,所以2的次幂会加一,最后变成\(2^k\)次方的时候,每个数最多出现两次,正好符合......
  • 一个可以拖拽缩放的div?
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"/><metahttp-equiv="X-UA-Compatible"content="IE=edge"/><metaname="viewport"content="width=de......
  • C++ signal(SIGFPE,handler) ignore division by 0 exception
    #include<stdexcept>#include<chrono>#include<csetjmp>#include<ctime>#include<fstream>#include<iostream>#include<iomanip>#include<signal.h>#include<sstream>#include<thread>#incl......
  • 【LGR-166-Div.4】洛谷入门赛17
    【LGR-166-Div.4】洛谷入门赛#17比赛地址这次是div4的难度,整体不算是很难,很适合小白玩家[10月入门赛-A]食堂题目描述为了给师生提供良好的用餐体验,洛谷小学的食堂坚持现炒、现做每一道菜肴。洛谷小学一共有\(a\)名老师和\(b\)名学生。食堂的营养师为每位师生的用餐进......
  • CodeForces 1895E Infinite Card Game
    洛谷传送门CF传送门容易转化成经典的有向图博弈模型。每张牌建一个点,若\(x\)能打败\(y\)就连一条\(x\toy\)的边。入度为\(0\)的点为必败态,之后类似拓扑排序倒推即可。具体就是若存在边\(u\tov\),若\(u\)为必败态则\(v\)为必胜态并加入队列;若\(v\)的所有前驱......
  • CF906 div2
    CF906div2A.Doremy'sPaint3题意给出一个序列,可以随意打乱顺序,问最后能否使得所有相邻两个元素的和相等。数据范围多组数据,\(2<=n<=100,1<=a_i<=10^5\)样例输入52893112411455233334100000100000100000100000样例输出YesYesNoNo......