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;
}