[codeforces 1397B] Power Sequence 特判+边界处理

Codeforces Round #666 (Div. 2)   参与排名人数13870

[codeforces 1397B]   Power Sequence   特判+边界处理

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址https://codeforces.com/contest/1397/problem/B

ProblemLangVerdictTimeMemory
B - Power Sequence GNU C++17Accepted31 ms1000 KB

题目大意:给出n个元素组成的数组a,可以将其排序后进行处理,可将处理的元素加1或减1,这样算一次计数,最后处理成c^0,c^1,c^2,......,c^(n-1)的数组,要求计数数量最小。

样例模拟如下:

3
1 3 2

排序后
1 2 3

2^2=4>=3,c=2
1-2^0+2-2^1+2^2-3=1

c--,c=1
1-1^0+2-1^1+3-1^2=3

输出最小值1



基本思路:模拟了样例发现,n越过了某一大小后(2^30=1073741824,2^63=9.223372037×10¹⁸,因元素最大值10^9,故n>63十分合理),c值只能为1,若n小于该数据时,找到数组中的最大元素a[n-1],若c^(n-1)>=a[n],可通过此时的c计算出计数数量ans1,紧接着c--,c^(n-1)<a[n],可通过此时的c计算出计数数量ans2,那么最小值一定发生在min(ans1,ans2).

AC代码如下:

#include <stdio.h>
#include <algorithm>
#define LL long long
#define maxn 100010
LL a[maxn],c,b,d,ans1,ans2;
using namespace std;
LL quick_pow(LL a,LL b){
	LL ret=1;
	while(b){
		if(b&1)ret=ret*a;
		a=a*a;
		b>>=1;
	}
	return ret;
}
int main(){
	int n,i;
	scanf("%d",&n);
	for(i=0;i<n;i++)scanf("%lld",&a[i]);
	if(n>63){//越过该值后,c==1
		for(i=0;i<n;i++)ans1+=a[i];
		ans1-=n;
		printf("%lld\n",ans1);
		return 0;
	}
	sort(a,a+n);
	c=1;
	while(1){
		if(quick_pow(c,n-1)>=a[n-1])break;
		c++;
	}
	for(i=0;i<n;i++){
		d=quick_pow(c,i);
		if(d>=a[i])ans1+=d-a[i];
		else ans1+=a[i]-d;
	}
	c--;//边界处理
	for(i=0;i<n;i++){
		d=quick_pow(c,i);
		if(d>=a[i])ans2+=d-a[i];
		else ans2+=a[i]-d;
	}
	printf("%lld\n",min(ans1,ans2));
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值