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
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
B - Power Sequence | GNU C++17 | Accepted | 31 ms | 1000 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;
}