codeforces.com/contest/251/problem/C

C. Number Transformation
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Little Petya likes positive integers a lot. Recently his mom has presented him a positive integer a. There's only one thing Petya likes more than numbers: playing with little Masha. It turned out that Masha already has a positive integer b. Petya decided to turn his number a into the number b consecutively performing the operations of the following two types:

  1. Subtract 1 from his number.
  2. Choose any integer x from 2 to k, inclusive. Then subtract number (a mod x) from his number a. Operation a mod x means taking the remainder from division of number a by number x.

Petya performs one operation per second. Each time he chooses an operation to perform during the current move, no matter what kind of operations he has performed by that moment. In particular, this implies that he can perform the same operation any number of times in a row.

Now he wonders in what minimum number of seconds he could transform his number a into number b. Please note that numbers x in the operations of the second type are selected anew each time, independently of each other.

Input

The only line contains three integers ab (1 ≤ b ≤ a ≤ 1018) and k (2 ≤ k ≤ 15).

Please do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64dspecifier.

Output

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

Examples
input
10 1 4
output
6
input
6 3 10
output
2
input
1000000000000000000 1 3
output
666666666666666667
Note

In the first sample the sequence of numbers that Petya gets as he tries to obtain number b is as follows: 10  →  8  →  6  →  4  →  3  →  2  →  1.

In the second sample one of the possible sequences is as follows: 6  →  4  →  3.

 题意:

给出 a b k

求a变到b的最小步数,每一步可以选择两种变化中的一种:a=a-1和a=a-a%i (2<=i<=k);

代码:

复制代码
//k最大只有15,首先要想到2~15的lcm必然是一个循环节,然后就可以利用分块的思想,分成(a-1)/lcm+1块,每一块
//的大小是lcm,然后中间整个块的可以计算(每一块最大不会超过360360),两边的剩余的也可以计算了。这里我用的
//记忆化bfs找的。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1000009;
int k,vis[MAXN];
int gcd_(int x,int y) { return y==0?x:gcd_(y,x%y); }
int lcm_(int x,int y) { return x/gcd_(x,y)*y; }
ll bfs(ll x,ll y)
{
    queue<ll>q;
    memset(vis,-1,sizeof(vis));
    q.push(x);
    vis[x-y]=0;
    while(!q.empty()){
        ll now=q.front();q.pop();
        if(now==y) return vis[0];
        for(int i=2;i<=k;i++){
            ll xx=now-now%i;
            if(xx<y||vis[xx-y]!=-1) continue;
            vis[xx-y]=vis[now-y]+1;
            q.push(xx);
        }
        ll xx=now-1;
        if(vis[xx-y]!=-1) continue;
        vis[xx-y]=vis[now-y]+1;
        q.push(xx);
    }
}
int main()
{
    ll a,b,ans=0;
    cin>>a>>b>>k;
    if(k==2){
        cout<<a-b<<"\n";
        return 0;
    }
    ll last=2;
    for(int i=3;i<=k;i++) last=lcm_(last,i);
    ll tmp1=a/last;
    ll tmp2=(b-1)/last+1;
    if(tmp1>tmp2) ans=bfs(a,tmp1*last)+(tmp1-tmp2)*bfs(last,0)+bfs(last*tmp2,b);
    else ans=bfs(a,b);
    cout<<ans<<"\n";
    return 0;
}
复制代码

 

posted @   luckilzy  阅读(470)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示