HDU 4294 Multiple [搜索]

  求一个K进制下是N的倍数的数,要求这个数使用的数字最少,数字个数相同时取较小的数。

  首先有一个结论,至多用两个数字可以构造任意数的倍数。假设只有一个数字吗,由这一个数字构成的数模N的结果只能是0~N-1,由抽屉原理可知必然存在两个数模N的结果相同,这两个数一减,结果有两个数字构成,模N的结果是0。

  然后就暴力BFS吧,队列中存的是余数,找到余数为0或者出现已经出现过的余数就返回。每次找到解比较跟新一下即可。

 1 #include <string.h>
 2 #include <stdio.h>
 3 #define MAXN 10005
 4 int n, k, num[2];
 5 int vis[MAXN], fa[MAXN], q[MAXN], front, rear;
 6 char st[MAXN], ans[MAXN], str[MAXN];
 7 int bfs(int nums)
 8 {
 9     memset(vis, 0, sizeof vis);
10     q[front = rear = 0] = 0, rear++;
11     while (front < rear) {
12         int u = q[front++];
13         for (int i = 0; i < nums; i++) {
14             int v = (u * k + num[i]) % n;
15             if (!vis[v] && !(u == 0 && num[i] == 0)) {
16                 fa[v] = u, st[v] = num[i] + '0';
17                 vis[v] = 1;
18                 if (v == 0) return 1;
19                 else q[rear++] = v;
20             }
21         }
22     }
23     return 0;
24 }
25 bool cmp(char *a, char *b) {
26     int lena = strlen(a), lenb = strlen(b);
27     if (lena != lenb) return lena < lenb;
28     for (int i = 0; i < lena; i++) {
29         if(a[i] != b[i]) return a[i] < b[i];
30     }
31     return 0;
32 }
33 int len = 0;
34 void getstr(int u) {
35     if (fa[u] != 0) getstr(fa[u]);
36     str[len++] = st[u];
37 }
38 void updateans() {
39     len=0; getstr(0); str[len] = '\0';
40     if (strcmp(ans, "a") == 0 || cmp(str,ans)) strcpy(ans, str);
41 }
42 int main() {
43     //freopen("test.in","r",stdin);
44     while (scanf("%d%d", &n, &k) != EOF) {
45         strcpy(ans, "a");
46         for (int i = 1; i < k; i++)
47             if (num[0] = i, bfs(1)) updateans();
48         if(strcmp("a", ans) == 0) {
49             for(int i = 0; i < k; i++)
50                 for(int j = i+1; j < k; j++)
51                     if(num[0] = i, num[1] = j, bfs(2)) updateans();
52         }
53         printf("%s\n",ans);
54     }
55     return 0;
56 }
原文地址:https://www.cnblogs.com/swm8023/p/2694603.html