CF1759F
-
因为每次只对原数加 \(1\),所以表示出来所有的数最多需要 \(p-1\) 次(一共 \(p\) 种数字,\(in[1]\) 已经被表示出来了)
-
对于输入数的最低位 \(in[1]\),如果有比他小的数没被表示出来,那么一定存在进位(进位过程中,所有大于 \(in[1]\) 的数全被表示出来了,进位后 \(in[1]\) 变为0),进位需要 \((p-1)-in[1]+1\) 步
-
找到没有被表示出来的最大的数 \(k\),表示出来他需要 \(k-in[1]\) 步
-
寻找 “没有被表示出来的最大的数” 时,根据鸽巢原理,范围是上限 \(limit\) 到 \(limit-n\)
-
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int t;
int n,p,in[101];
map <int,int> rec;
signed main(){
// freopen("1.in","r",stdin);
cin>>t;
while(t--){
cin>>n>>p;
for(int i=1;i<=n;i++){
cin>>in[i];
rec[in[i]]++;
}
int ans=0,limit=p-1; //步数,“没有被表示出来的最大的数” 的上限
bool add=0; //是否需要进位
reverse(in+1,in+1+n); //最低位在前,方便进位
for(int i=in[1];i>=max(in[1]-n,1ll*0);i--){
if(!rec[i]){
add=1; //有比个位小的数没表示出来,需要进位
break;
}
}
if(add){
ans=ans+((p-1)-in[1]+1);
limit=in[1]-1; //进位过程中比in[1]大的数全部被表示出来了,可能的“没有被表示出来的最大的数”最大为in[1]-1
in[1]=0; in[2]++;
for(int i=2;i<=n;i++){
if(in[i]>=p){
in[i+1]=in[i+1]+(in[i]/p);
in[i]%=p;
}
}
for(int i=1;i<=n;i++) //进位后统计是否有新出现的数
rec[in[i]]++;
if(in[n+1]) rec[in[n+1]]++;
}
for(int i=limit;i>=max(limit-n,1ll*0);i--){
if(!rec[i]){
ans=ans+(i-in[1]); //最大的“没有被表示出来的最大的数”
break;
}
}
cout<<ans<<"\n";
rec.clear();
memset(in,0,sizeof(in));
}
}
浙公网安备 33010602011771号