题意求k的倍数的最小数位和
范围是10^5 不能直接枚举
1 . 我们可以想到如果一个数 模 k 等于 0 那就是 k 的倍数
2 . 如果从1开始到任意一个数, 我们可以乘10 或者 加一来实现
3 . 乘10 数位和不变,加一 数位和 加一(末尾是9的情况也一样)
4 . 通过这两种操作得到的第一个k的倍数数位和一定是最小的,我们在模k下进行操作
也就是找到的第一个0
可以最短路来实现 或者 用双向队列deque来实现两种操作
答案就是 1 到 第一个0的值
最短路代码
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int N = 1e5 + 10;
const int M = 1e6 + 10;
struct node
{
int to, next, w;
bool operator < (const node& a) const {
return w > a.w;
}
}e[M];
int head[N],cnt;
void add(int u, int v, int w)
{
e[cnt] = (node){v,head[u],w};
head[u] = cnt++;
}
void init()
{
cnt = 0;
memset(head,-1,sizeof(head));
}
bool vis[N];
int dis[N];
int dij(int st,int ed)
{
priority_queue<node> q;
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[st] = 0;
q.push((node){st, 0, 0});
while (!q.empty()) {
node u = q.top();
q.pop();
if(vis[u.to]) continue;
vis[u.to] = 1;
for (int i = head[u.to]; ~i; i = e[i].next) {
node k = e[i];
if (dis[k.to] > dis[u.to] + k.w) {
dis[k.to] = dis[u.to] + k.w;
q.push((node){k.to, 0, dis[k.to]});
}
}
}
return dis[ed];
}
int main()
{
init();
int k;
scanf("%d",&k);
for(int i=0;i<k;i++) {
add(i,i*10%k,0);
add(i,(i+1)%k,1);
}
int ans = dij(1,0);
printf("%d\n",ans + 1);
return 0;
}
双向队列代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
bool vis[N];
typedef pair<int,int> P;
deque<P> q;
int main()
{
int k;
scanf("%d",&k);
q.push_back(make_pair(1,1));
while(!q.empty())
{
P x = q.front();
q.pop_front();
if(vis[x.first]) continue;
vis[x.first] = 1;
if(x.first == 0) {
printf("%d\n",x.second);
break;
}
q.push_front(make_pair(x.first * 10 % k,x.second));
q.push_back(make_pair((x.first + 1) % k,x.second + 1 ) );
}
return 0;
}