CodeForces 346C Number Transformation II

Number Transformation II

题解:

对于操作2来说, a - a % x[i] 就会到左边离a最近的x[i]的倍数。

也就是说 [ k * x[i] + 1,  (k+1)* x[i] -1 ]这段区间的的数都会走到 k * x[i]上。

所以对于每个位置都先计算出他到右边最远的覆盖位置。

然后在反着求出每个位置能往左走走到的最远的位置。

 

代码:

#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("___.txt","r",stdin);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL _INF = 0xc0c0c0c0c0c0c0c0;
const LL mod =  (int)1e9+7;
const int N = 1e6 + 100;
const int M = 3e7;
vector<int> in[N], out[N];
int x[N], to[N], rto[N];
int n;
int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) scanf("%d", &x[i]);
    int f = 0;
    int a, b;
    scanf("%d%d", &a, &b);
    sort(x+1, x+1+n);
    n = unique(x+1, x+1+n) - (x+1);
    for(int i = 0; i <= a-b; ++i) rto[i] = i + 1;
    for(int i = 1; i <= n; ++i){
        LL start = b / x[i] * x[i];
        if(start < b)  start += x[i];
        while(start < a){
            LL r = start + x[i] - 1;
            if(r > a) r = a;
            rto[start-b] = max(rto[start-b], (int)(r-b));
            start = r + 1;
        }
    }
//    cout << "ok1" << endl;
    for(int l = 0, r = 1; l <= a-b; ++l){
        int nr = rto[l];
        while(r <= nr){
            to[r] = l;
            ++r;
        }
    }
    int ans = 0, now = a-b;
    while(now){
        ans++;
        now = to[now];
    }
    cout << ans << endl;

    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/MingSD/p/10885388.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值