A. Find a Number
Solved By 2017212212083
题意:$找一个最小的n使得n % d == 0 并且 n 的每一位数字加起来之和为s$
思路:
定义一个二元组$<d, s>$ 表示当前状态模d的值,以及每一位加起来的值
跑最短路,从$<0, 0> 跑到 <0, s>$
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 1e5 + 10; 6 const int INF = 0x3f3f3f3f; 7 #define N 510 8 #define M 5010 9 10 int d, s, cnt; 11 char ans[maxn]; 12 int dis[N][M]; 13 int inq[N][M]; 14 int vis[N][M]; 15 16 struct node{ 17 int remind; 18 int sum; 19 node(){} 20 node(int remind, int sum) :remind(remind), sum(sum){} 21 }; 22 23 void Init() 24 { 25 cnt = -1; 26 memset(inq, 0, sizeof inq); 27 memset(dis, 0x3f, sizeof dis); 28 memset(vis, 0, sizeof vis); 29 } 30 31 void BFS() 32 { 33 queue<node>q; 34 dis[0][0] = 0; 35 q.push(node(0, 0)); 36 inq[0][0] = 1; 37 while(!q.empty()) 38 { 39 node st = q.front(); 40 q.pop(); 41 inq[st.remind][st.sum] = 0; 42 for(int i = 0; i < 10; ++i) 43 { 44 node now = node((st.remind * 10 + i) % d, st.sum + i); 45 if(now.sum > s) break; 46 if(dis[now.remind][now.sum] > dis[st.remind][st.sum] + 1) 47 { 48 dis[now.remind][now.sum] = dis[st.remind][st.sum] + 1; 49 if(!inq[now.remind][now.sum]) 50 { 51 inq[now.remind][now.sum] = 1; 52 q.push(now); 53 } 54 } 55 } 56 } 57 } 58 59 int DFS(int D,int S) 60 { 61 if(D == 0 && S == s) return 1; 62 for(int i = 0; i < 10; ++i) 63 { 64 int td = (D * 10 + i) % d; 65 int ts = S + i; 66 if(ts > s) break; 67 if(vis[td][ts]) continue; 68 if(dis[D][S] + 1 != dis[td][ts]) continue; 69 ans[++cnt] = i; 70 if(DFS(td, ts)) return 1; 71 --cnt; 72 } 73 vis[D][S] = 1; 74 return 0; 75 } 76 77 int main() 78 { 79 while(~scanf("%d %d", &d, &s)) 80 { 81 Init(); 82 BFS(); 83 if(dis[0][s] == INF) 84 { 85 puts("-1"); 86 continue; 87 } 88 DFS(0, 0); 89 for(int i = 0; i <= cnt; ++i) printf("%d", ans[i]); 90 puts(""); 91 } 92 return 0; 93 }