[??记录]AT3621 [ARC084B] Small Multiple

command_block

2021-05-14 07:13:10

Personal

**题意** : 给定整数 $k$。 求 $c\in \rm Z^+$ ,使得 $ck$ 在十进制下的数位和最小,输出这个最小值。 $k\leq 10^5$。 ------------ 若 $k=2^t$ ,则要配上 $c=5^t$ 得到最优方案 $10^t$。此时 $c\geq 10^{11}$ ,故不能直接枚举 $c$。 考虑我们是如何构造一个数 $m$ 的。 - $m\leftarrow m\times 10$ :数位和不变。 - $m\leftarrow m+1$ : 若不进位,数位和加一,否则数位和可能减少。 考虑同余最短路,记 $dis_i$ 表示模 $k=i$ 的数中数位和最小的。 连边 $i\rightarrow 10i\bmod k$ ,边权为 $0$。 连边 $i\rightarrow (i+1)\bmod k$ ,边权为 $1$。 然后跑 $01\ \rm BFS$ 即可,答案是 $dis_0$。 复杂度 $O(k)$。 ```cpp #include<algorithm> #include<cstdio> #include<vector> #define pb push_back #define MaxN 100500 using namespace std; const int INF=1000000000; vector<int> g[MaxN],l[MaxN]; int k,q[MaxN<<1],dis[MaxN]; bool in[MaxN]; int main() { scanf("%d",&k); for (int i=0;i<k;i++){ dis[i]=INF; g[i].pb((i+1)%k);l[i].pb(1); g[i].pb(i*10%k);l[i].pb(0); } int ql,qr; dis[1]=1;q[ql=qr=k]=1; while(ql<=qr){ int u=q[ql++]; if (in[u])continue; in[u]=1; for (int i=0,v;i<g[u].size();i++) if (dis[v=g[u][i]]>dis[u]+l[u][i]){ dis[v]=dis[u]+l[u][i]; if (l[u][i])q[++qr]=v; else q[--ql]=v; } }printf("%d",dis[0]); return 0; } ```