CF83B Doctor题解

博客内容涉及一个数学和算法结合的问题,讨论了如何利用周期性规律解决一个关于数列在每次操作中减去最大值直至归零的题目。作者提出了一种避免二分搜索的策略,通过计算每个数被消除的周期和顺序,最终实现模拟消除过程。代码部分展示了C++实现的解决方案。
摘要由CSDN通过智能技术生成

传送门 点我

推销 点我

题意

翻译非常好懂,非常敬业。

思路

看到很多题解是二分的,感觉,是不是有点小题大做了……
提供一个利用数学中的周期问题的方法。
假设每一个数都不会被消去,你只需要不停地减,那么相信大家一定都会做,即使那个 k 这么大。
但一个数是会被消去的。
我们来考虑一下:如果一个数要被消去,那么它的数值要变成 0,所以我们可以算出,假设它的数值为 x,一共有 y 个数而且其他数都不比它小,那么它理应会在第 (x - 1 ) \times y + 1 次被消去。
但是这样有两个限制:

  1. 这个数不一定在第一位。
  2. 剩下的数不一定都不比它小。

这个时候,我们是否可以把最后的那一下补完一个周期,那么就可以对其进行排序,然后从数值小的开始一个个消去,最后的几个再暴力模拟一下就行了!

Code

#include<bits/stdc++.h>
using namespace std;
long long n,m,i,sum,x,flag;
struct Node{
	long long x,i;
}a[100010];
bool cmp(Node x,Node y){return x.x<y.x;}
bool cmp1(Node x,Node y){return x.i<y.i;}
int main(){
	scanf("%lld%lld",&n,&m);
	for (i=1;i<=n;i++) scanf("%lld",&a[i].x),a[i].i=i;
	sort(a+1,a+n+1,cmp);
	for (i=1;i<=n;i++)
		if (sum+(a[i].x-x)*(n-i+1)<=m) sum=sum+(a[i].x-x)*(n-i+1),x=a[i].x;
		else break;
	if (i>n&&sum<m){printf("-1\n");return 0;}
	else if (i>n&&sum==m) return 0;
	x=x+(m-sum)/(n-i+1);m=(m-sum)%(n-i+1);
	i=1;sort(a+1,a+n+1,cmp1);
	while (m>0){
		if (a[i].x>x) a[i].x--,m--;
		i=i%n+1;
	}
	int h=i;
	for (i=1;i<=n;i++,h=h%n+1) if (a[h].x>x) printf("%lld ",a[h].i);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值