codeforces 346C Number Transformation II

傳送門

題意:

給兩個數字a,b,有兩個操作,第一個操作直接-1,第二個操作是a-a\ MOD\ x_i,求a變成b的最少操作數

題解:

很明顯令f_k表示由b+k到b的最少操作數,假設b,b+k可以一步操作到達,

t=1 \quad f_k\ =\ f_{k-t}+1\\t>1\quad IF\quad f_k\ = \ f_{k-t}\\f_{k-1}\ \leq \ f_{k-t}+1 \ =\ f_k\\ \because f_{k-1}=f_{k-t}+1\or\ Better\\\therefore f_{k-1}\ \leq \ f_{k-t}+1 \ =\ f_k

由此得出f_k單調上升,即可貪心每次減去最大值

注意:到x_i會有重複,需要用到unique函數函數

unique(a+1,a+n+1)=去重後的數字

當然也有別的思路:考慮到[b+1,b+\max(x_i)]這是第一步可達區間,再從這裏可以依次擴展到其他步的可達區間[b+\max(x_i)+1,\dots],有機會再寫吧

代碼:

#include"algorithm"
#include"iostream"
#include"string.h"
#include"stdio.h"
#define ll long long
using namespace std;
const int Maxn=100005;
ll x[Maxn];
int cmp(int a,int b)
{
	return a>b;
}
int main()
{
//	freopen("text.in","r",stdin);
	int n,ans=0;
	ll a,b;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%lld",&x[i]);
	scanf("%lld%lld",&a,&b);
	sort(x+1,x+n+1,cmp);
	int len=unique(x+1,x+n+1)-(x+1);
	while(a>b)
	{
		ll t=a;
		for(int i=1;i<=len;i++)
		{
			if(a-a%x[i]<b)x[i--]=x[len--];
			else t=min(t,a-a%x[i]);
		}
		a=min(t,a-1),ans++;
	}
	printf("%d",ans);
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章