1. 程式人生 > >CodeForces - 346C- Number Transformation II(貪心+暴力。。)

CodeForces - 346C- Number Transformation II(貪心+暴力。。)

CodeForces - 346C- Number Transformation II

You are given a sequence of positive integers x1, x2, …, xn and two non-negative integers a and b. Your task is to transform a into b. To do that, you can perform the following moves:

subtract 1 from the current a;
subtract a mod xi (1 ≤ i ≤ n) from the current a.
Operation a mod xi means taking the remainder after division of number a by number xi.

Now you want to know the minimum number of moves needed to transform a into b.

Input
The first line contains a single integer n (1 ≤  n ≤ 105). The second line contains n space-separated integers x1, x2, …, xn (2 ≤  xi ≤ 109). The third line contains two integers a and b (0  ≤ b ≤  a ≤ 109, a - b ≤ 106).

Output
Print a single integer — the required minimum number of moves needed to transform number a into number b.

Examples
Input
3
3 4 5
30 17
Output
6
Input
3
5 6 7
1000 200
Output
206

  • 題目大意:
    給你兩個數a,b(a>b)還有一個數組c[]。問最少經過多少步可以讓a變成b。每一步可以進行兩種操作中的一種 1.a-1 2.a-a%c[i]
  • 解題思路;
    每次找能減的最大的數,貪心的思想,一直到減到a==b為止。
    先把c陣列排序,每次找能減的最大的數
for(int i=n-1;i>=0;i--)//找一個減的最多的 
		{
			if(a-a%c[i]>=b)
				tmp=min(tmp,a-a%c[i]);
		}

然後就有個小小的提速的方法。就是如果當前的a-a%c[n]<b的話,那麼這個c[n]在後面就沒用了,就可以直接摘除了。

while(n>0)//去掉不可能的 
		{
			if(a-a%c[n-1]<b)
				n--;
			else
				break;
		}

還有個地方很坑,,,就是c陣列需要去重,不然就一直T。。。

n = unique(c,c+n)-c;

總之,,我感覺這個題蠻坑的,1e5的n,然後每次都掃一遍更新一下,每次掃一遍。。。a,b之間差1e6,極端的情況會掃很多很多次把,我一直在找規律,找了很久也沒找出來,看了題解發現竟然是暴力。。可能是我太菜了。

  • AC程式碼:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define ll long long
using namespace std;
const int maxn=1e5+10;
int n,a,b;
int c[maxn];
int main()
{
	int n;
	scanf("%d",&n); 
	for(int i=0;i<n;i++)
		scanf("%d",&c[i]);
	sort(c,c+n);
	n = unique(c,c+n)-c;
	scanf("%d%d",&a,&b);;
	int tmp;
	int cnt=0;
	while(a>b)
	{
		tmp=a-1;//a可以直接減一 
		for(int i=n-1;i>=0;i--)//找一個減的最多的 
		{
			if(a-a%c[i]>=b)
				tmp=min(tmp,a-a%c[i]);
		}
		a=tmp;
		cnt++;
		if(a==b)
			break; 
		while(n>0)//去掉不可能的 
		{
			if(a-a%c[n-1]<b)
				n--;
			else
				break;
		}
	}
//	cout<<cnt<<endl;
	printf("%d\n",cnt); 
	return 0;
}