• UPC 6616 Small Mulitple


    D - Small Multiple

    题目传送门
    Time limit : 2sec / Memory limit : 256MB
    Score : 700 points

    Problem Statement

    Find the smallest possible sum of the digits in the decimal notation of a positive multiple of K.
    Constraints

    2K105
    K is an integer.
    
    • 1
    • 2
    • 3

    Input

    Input is given from Standard Input in the following format:
    
    K
    
    • 1
    • 2
    • 3
    • 4

    Output

    Print the smallest possible sum of the digits in the decimal notation of a positive multiple of K.
    
    • 1
    • 2

    Sample Input 1

    6

    Sample Output 1

    3

    12=6×2 yields the smallest sum.

    Sample Input 2

    41

    Sample Output 2

    5

    11111=41×271 yields the smallest sum.

    Sample Input 3

    79992

    Sample Output 3

    36

    Solution

    疯狂从数的角度出发,找了一下午规律而毫无结果的我……桑森。
    最后发现,这题竟然可以写最短路??
    贴一发Atcoder的官方题解:英文题解_传送门
    这种方法十分巧妙——
    首先,让我们转换一下思维,从数到图。先说说操作,对于任意一个0..k-1之间的整数x,将x看做一个点。由于从x出发可以引出两项基本操作:
    (1)x*=10,此时x的各位数字和不发生改变,此操作可以转换成从x到x*10%k连一条有向边,权值0;
    (2)x++,此时x的各位数字和也加一,此操作可以转换成从x到(x+1)%k连一条有向边,权值1。
    这样图中有k个点(0..k-1),2*k条边。
    然后, 关于合理性和含义,阐释如下。所有对k同余的数目可以看做图中的同一个点,当我们从点1出发,沿着构造好的有向图的边走到0点时,就相当于走到了一个k的正整数倍数的点值,不妨设其为ak。而这一路走来经过的所有边的权值之和,也就是逐步或加1或加0得到的总和,正是ak的各位数值总和减一。(这一路走来是经过了连接点与点的路径,而出发点是1不是0;出发点显然不能与终点相同,故不能是0;若出发点不是1而是1后面的点,难免会忽略了一些在那后面的点之前的可能的比较优的路径。因此应从1到0走一趟)。易知此有向图的最短路径长度减一就是答案。
    (3)k<=1e5,点数k,边数2k,跑dijkstra即可。

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N = 100001;
    struct node{
        int v,nxt,cost;
    }edge[N<<1];
    int head[N],k,tot;
    int q[N*8],l,r,u,v;
    int dist[N];
    void addEdge(int u,int v,int val) {
        edge[++tot].v=v;
        edge[tot].cost=val;
        edge[tot].nxt=head[u];
        head[u]=tot;
    }
    int main() {
        //freopen("out.txt","w",stdout);
        scanf("%d",&k);
        for (int i=0;i<k;++i) {
            addEdge(i,i+1==k?0:i+1,1);
            addEdge(i,i*10%k,0);
            dist[i]=N;
        }
        dist[1]=0;
        l=-1;
        r=0;
        q[0]=1;
        while (l<r) {
            u = q[++l];
            for (int i=head[u];i;i=edge[i].nxt) {
                v=edge[i].v;
                if (dist[u]+edge[i].cost<dist[v]) {
                    dist[v]=dist[u]+edge[i].cost;
                    q[++r]=v;
                }
            }
        }
        printf("%d
    ",dist[0]+1);
        return 0;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
  • 相关阅读:
    ModernUI教程:使用预定义的页面布局
    ModernUI教程:第一个ModernUI应用(采用项目模板)
    ModernUI教程:第一个ModernUI应用(手动编写)
    ModernUI教程:目录 (完结)
    ScreenOS学习笔记
    子网划分
    Cisco IOS版本命名规则
    ThinkPHP的Auth类认证
    Excel 2007中自定义数字格式前要了解的准则
    float元素的父元素自适应高度
  • 原文地址:https://www.cnblogs.com/bianzhuo/p/9463281.html
Copyright © 2020-2023  润新知