Multiple
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 616 Accepted Submission(s): 159
Problem Description
Given a positive integer N, you’re to solve the following problem:
Find a positive multiple of N, says M, that contains minimal number of different digits in base-K notation. If there’re several solutions, you should output the numerical smallest one. By saying numerical smallest one, we compar their numerical value, so 0xAhex < 11dec.
You may assume that 1 <= N <= 104 and 2 <= K <= 10.
Input
There’re several (less than 50) test cases, one case per line.
For each test case, there is a line with two integers separated by a single space, N and K.
Please process until EOF (End Of File).
Output
For each test case, you should print a single integer one line, representing M in base-K notation,the answer.
Sample Input
10 8
2 3
7 5
Sample Output
2222
2
111111
/*
关于数论中的鹊巢原理:对于M%N,结果只能为0~N-1,那么如果有N+1个不同的M,
就肯定有两个数模N的结果相同。设这两个数为M1,M2(M2>M1),则有(M2-M1)%N==0
此题求在K进制下,用尽量少的数字拼成一个K进制数,使得该数对应的十进制数可以被
N整除。那么设数字为x,K进制数有x,xx,xxx,...(xxx...xxx)(N+1个x),那么这些数里面,
肯定有两个数模N的结果是相同的,两数想减有xxx...000是可以被N整除的。故有此可知,
对于任意一个数N,它的倍数最多只需两个不同的数字拼接而成。
所以可以用bfs完成每个数的枚举:
首先枚举只需一个数字拼接而成的,根据数值大小确定答案。
如果无法用一个数字拼接而成,则枚举两个数字,同样根据数值大小更新答案。值得注意
的是,更新答案是判断两个数字的大小。那么首先是判断长度,长度小的数,其值也肯定
小;长度相同再从高位到低位判断每一位的大小。
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define SIZE 10086
using namespace std;
bool vis[SIZE];
int pre[SIZE],digit[2];
char ans[SIZE],tem[SIZE],now[SIZE];
int N,K,len;
queue <int> Q;
bool bfs(int num)
{
while(!Q.empty())Q.pop();
memset(vis,0,sizeof(vis));
int cur,nex;
Q.push(0);
while(!Q.empty())
{
cur = Q.front();
Q.pop();
for(int i=0; i<num; i++)
{
nex = (cur*K+digit[i])%N;
if(cur == 0 && digit[i] == 0)
continue;
if(!vis[nex])
{
vis[nex] = true;
pre[nex] = cur; //记录搜索路径
tem[nex] = (digit[i] + '0'); //对应路径
if(nex == 0)
return true;
Q.push(nex);
}
}
}
return false;
}
bool cmp(char *a,char *b) //比较大小
{
int len1 = (int)strlen(a), len2 = (int)strlen(b);
if(len1 != len2)
return len1 < len2;
for(int i=0; i<len1; i++)
if(a[i] != b[i])
return a[i] < b[i];
return false;
}
void getStr(int st) //从余数为0根据路径往回找,得到该数。
{
if(pre[st] != 0)
getStr(pre[st]);
now[len++] = tem[st];
}
void update()
{
len = 0;
getStr(0);
now[len] = '\0';
if(ans[0] == '\0' || cmp(now,ans))
strcpy(ans,now);
}
int main()
{
while(~scanf("%d%d",&N,&K))
{
ans[0] = '\0';
memset(pre,0,sizeof(pre));
for(int i=1; i<K; i++)
{
digit[0] = i;
if(bfs(1))
update();
}
if(ans[0] == '\0')
{
for(int i=0; i<K; i++)
for(int j=i+1; j<K; j++)
{
digit[0] = i,digit[1] = j;
if(bfs(2))
update();
}
}
printf("%s\n",ans);
}
return 0;
}