abc077d <思维 + 最短路 (将构造数字过程视为最短路)>

D - Small Multiple

// https://atcoder.jp/contests/abc077/tasks/arc084_b
// <思维 + 最短路>
// 参考:
// 1. https://www.cnblogs.com/BaseAI/p/13885049.html <同余最短路>
// 2. https://blog.csdn.net/weixin_44178736/article/details/108390895

// 思路:
// 1. 假设有k的倍数x, 其最高位为i, 现在从高位到低位构造x;
// 2. x是k的倍数, 可表示为 x % k = 0
// 3. 当构造过程中, 已经构造了部分高位, 现在有数 y,
//  则若在低位添加数位 j, 则 y 变为 y*10 + j;
// 4. 在构造x的过程中, 正在构造的数y实际上仅需在模k意义下进行,
//  即, 当不断向y的低位添加数位时, y总是%k, 保持 0<=y<k;
// 5. 则构造过程中y一共仅有 0~k-1这k个有限的状态, 每个状态视为一个结点;
//  构造过程视为节点间的跳转, 若视为最短路问题, 则终点必然为 0 (即 %k=0 );
//  起点可为 1~9 (即x的最高位的数字, 注意不能为0, 为前导零);
// 6. 图中所有可能的边, 可通过 u (1~k-1) 向 v = 10*u+i (i= 0~9) 连接边得到
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
using LL = long long;
const int N = 1e5 + 10;

struct Node
{
    int dis, u;
    bool operator<(Node const &t) const
    {
        return dis > t.dis;  // 小根堆
    }
};

struct Edge
{
    int v, w;
};

vector<Edge> adj[N];

int dis[N];
bool st[N];

void dijkstra()
{
    priority_queue<Node> q; 
    memset(dis, 0x3f, sizeof dis);
    for (int i = 1; i <= 9; i ++) q.push({i, i}), dis[i] = i;  // 可视为一个虚起点向这9个节点连边, 权重为i
    while(q.size())
    {
        int u = q.top().u; q.pop();
        if(st[u]) continue;
        st[u] = true;
        for (auto [v, w]: adj[u])
        {
            
            if (dis[u] + w < dis[v])
            {
                dis[v] = dis[u] + w;
                q.push({dis[v], v});
            }
        }
    }
}

void solv()
{
    int k;
    cin >> k;
    for (int u = 1; u < k; u ++)
        for (int i = 0; i <= 9; i ++)
        {
            int v = (u * 10 + i) % k;
            adj[u].push_back({v, i});
        }
        
    dijkstra();
    cout << dis[0] << endl;
}

int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int T = 1;
	// cin >> T;
    while (T --)
    {
        solv();
    }
    return 0;
}

posted @   O2iginal  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示