• ABC007D Small Multiple[最短路]


    题意:求$K$的倍数中数位和的最小值。

    一开始有一种思路:由于产生答案的数字可能非常大,不便枚举,考虑转化为构造一个数字可以有$xmod k=0$。然后二分答案数位和,数位DP检验是否存在,但是由于数位DP还是局限于有限大小的数字,所以并不可行。`````

    套路见少了。实际上,这种构造数字满足某些条件的,一定可以把目标数字看成是一位一位写下来的,比如$114514$,可以看成逐步写下$1,1,4,5,1,4$不断$ imes 10$做加法的结果。所以考虑设$dis_i$为所有$xmod k=i$的同余类中数位和最小的,然后考虑从当前的这个状态开始写下一位,即连边$i o (10i+j)mod k$,边权$j$,然后最初从$dis_{1sim 9}$(首位)为源点跑最短路,求$dis_0$即可。

    atcoder的公式题解给的思路差不多,对于每个数,可以选择加$1$或者乘$10$,前者连边权为$1$,后者连边权$0$,和上面差不多,然后跑$01$最短路。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 #define dbg(x) cerr << #x << " = " << x <<endl
     8 #define dbg2(x,y) cerr<< #x <<" = "<< x <<"  "<< #y <<" = "<< y <<endl
     9 using namespace std;
    10 typedef long long ll;
    11 typedef double db;
    12 typedef pair<int,int> pii;
    13 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    14 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    15 template<typename T>inline bool MIN(T&A,T B){return A>B?(A=B,1):0;}
    16 template<typename T>inline bool MAX(T&A,T B){return A<B?(A=B,1):0;}
    17 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    18 template<typename T>inline T read(T&x){
    19     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    20     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    21 }
    22 const int N=1e5+7;
    23 struct thxorz{int nxt,to,w;}G[N*11];
    24 int Head[N],tot;
    25 int n;
    26 inline void Addedge(int x,int y,int z){G[++tot].to=y,G[tot].nxt=Head[x],Head[x]=tot,G[tot].w=z;}
    27 int dis[N];
    28 priority_queue<pii,vector<pii>,greater<pii> > pq;
    29 #define y G[j].to
    30 inline void dij(){
    31     memset(dis,0x3f,sizeof dis);for(register int i=1;i<10;++i)MIN(dis[i%n],i),pq.push(make_pair(dis[i%n],i%n));
    32     while(!pq.empty()){
    33         int d=pq.top().first,x=pq.top().second;pq.pop();
    34         if(d^dis[x])continue;//dbg2(x,d);
    35         if(x==0)return;
    36         for(register int j=Head[x];j;j=G[j].nxt)if(MIN(dis[y],d+G[j].w))pq.push(make_pair(dis[y],y));
    37     }
    38 }
    39 #undef y
    40 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
    41     read(n);
    42     for(register int i=1;i<n;++i)for(register int j=0;j<10;++j)Addedge(i,(10*i+j)%n,j);
    43     dij();
    44     return printf("%d
    ",dis[0]),0;
    45 }
    View Code

    总结:构造数字题常用思路or最短路常用思路:逐步拆分、分解“代价”为每一步的边的边权。

  • 相关阅读:
    Springboot-Static-Resource
    Springboot-Listener
    Springboot--servlet 、filter
    java 面试-- java框架-mybaits
    SVN备份教程(二)
    SVN备份教程(一)
    深入浅出MongoDB(三)环境搭建
    关于在c#中引用外部dll文件,在页面中找不到命名空间
    在win8中如何实现下拉刷新的功能
    C# treeview控件部分节点添加checkbox
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/11635603.html
Copyright © 2020-2023  润新知