Codeforces Round #666 (Div. 2) B Power Sequence(思维+暴力)

http://codeforces.com/contest/1397/problem/B
题目大意:给定给一个长度为n的序列a,以下标0为开始.定义一个序列是牛逼的,当且仅当序列a里的元素满足ai=cii.其中c为某个任意整数,只要有一个c满足即可(即c不是指定的,存在一个c满足即可).现在可以任意重排整个序列,并用1的代价使序列里任意一个元素的值增加一或减少一,问把整个序列变成一个牛逼的序列最少需要多少的代价.
思路:
第一步题目给定了一个重排的操作,显然因为一个牛逼的序列一定是一个上升的序列(除了c=1的特殊情况,其他的都是严格上升的),所以一个比较直接的想法就是把整个序列按升序排序,再枚举所有可能的c,算出每个值的消耗,因为排序之后比不排序一定更好,所以算出来的结果一定正确.那么这里有一个问题:c的取值范围是多少.
从直觉上来说,这个题目的数据范围相当的大,c的取值也一定和a序列的和有关,而且可以猜到cc的取值范围是很有限的,而这个和可以到达1014.不过一个牛逼序列,同时是一个等比数列,在cc增大的过程中整个牛逼序列的和会上升的非常快,因此上界会很快的达到.那么对于单个的c的上界,不妨就按1e18作为INF,之后因为是一个等比数列,一共有n项,那么c的上界设置成是INF1n,因为整个牛逼序列的和不能过大,这样就可以保证了,当然这个上界并不准确,而且运算过程中可能会爆掉llll.所以在具体写的时候,是一步一步的计算出当前的和,如果已经超过了答案,那么就直接过掉,避免溢出.其次可以猜测这个复杂度是比较正常的,因为c并不会有多少个取值.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+7;
const ll INF = 1e18;
int a[N];
int main()
{
	int n;scanf("%d",&n);ll res = INF,s = 0;
	for(int i = 1;i <= n;++i)	scanf("%d",&a[i]),s += a[i];
	sort(a + 1,a + 1 + n);
	int limit = pow(INF,1.0/n);
	for(ll c = 1;c <= limit;++c)
	{
		ll loc = llabs(1 - a[1]),k = 1;
		for(int i = 2;i <= n;++i)
		{
			k *= c;loc += llabs(a[i] - k);
			if(loc > res)	break;
		}
		res = min(res,loc);	
	}
	printf("%lld",res);
    return 0;
}	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

deebcjrb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值