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));
	}
}
posted on 2023-06-02 16:19  Bubble_e  阅读(26)  评论(0)    收藏  举报