Atcoder - Small Multiple

原题:Small Multiple

原题大意

给一个数K,在K的整数倍里,找出数位和最小的,并输出和

算法分析

首先引入图论,求一个数的数位和,可以看成一张有向图求最短路,图上的每个顶点都是整数,起点是1,数字v到数字v+1之间的值为1,数字v到数字v*10的值为0,求x的数位和就是求1到x的最短路的距离加上1。

这里求K的整数倍,可以把图压缩到K个点,因为如果两个数mod K的值相同,我们可以认为是同一个点(如2 和 20 mod 6),所以就是求从1到0的最短路。
因为只含有1和0,所以可以用双端队列来优化(每个值取出来要么不变,要么加1,不变的放到队首,加1的放到队尾,队列里的值一定是非递减的)。

程序代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+50;
typedef pair<int, int> ii;
int solve(int K){
    deque<ii> dq;
    vector<int> vis(K, 0);
    dq.push_front(ii(1,1));
    while(!dq.empty()){
        ii p = dq.front(); dq.pop_front();
        int curr = p.first, cnt = p.second;
        if(curr == 0) return cnt;

        vis[curr] = 1;
        int next = (curr+1) % K;
        if(vis[next] == 0)
            dq.push_back(ii(next, cnt+1));

        next = (curr * 10) % K;
        if(vis[next] == 0)
            dq.push_front(ii(next, cnt));
    }
}
int main(){ 
    int K; cin >> K;
    cout << solve(K) << endl;
    return 0;
}