Different Digits
Time Limit: 10000/4000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1789 Accepted Submission(s): 541
Problem Description
Given a positive integer n, your task is to find a positive integer m, which is a multiple of n, and that m contains the least number of different digits when represented in decimal. For example, number 1334 contains three different digits 1, 3 and 4.
Input
The input consists of no more than 50 test cases. Each test case has only one line, which contains a positive integer n ( 1<=n < 65536). There are no blank lines between cases. A line with a single `0' terminates the input.
Output
For each test case, you should output one line, which contains m. If there are several possible results, you should output the smallest one. Do not output blank lines between cases.
Sample Input
7 15 16 101 0
Sample Output
7 555 16 1111
题目分析:
题目大意就是求一个数能整除n,并且数中包含的不同数字最少。直接的想法就是去枚举每一位的数,但是啥时候停止,题目有没有位数的限制,难道要一直找下去?所以这里就应该想到有个限制条件,限制搜索的深度。题目中说的是找一个数的倍数,这里不难想到用余数判重。还有一个点就是:对于任意的整数 n ,必然存在一个由不多于两个的数来组成的一个倍数。 因为 a ,aa , aaa…… 取 n+1 个,则由鸽笼原理,必有两个模 n 余数相同,相减即得 n 的倍数 m 。而 m 只由 a 、 0 组成。也就是说枚举时可以只枚举一个数的情况和两个数的情况。
代码:https://blog.youkuaiyun.com/driver13/article/details/49287299
#include<iostream>
#include<string.h>
#include<string>
using namespace std;
/*
Node: d:当前位的数字 val:余数 pre:前一位数字在队列中的位置 cnt:数的位数
a: 保存枚举的数(实际只用到了a[1],a[2],只用a[1]表明求的数只有1个数组成的情况,a[1],a[2]都用表明求的数有两个不同的情况)
ans: 存最终的答案
tans: 存中间求解过程中的答案,不一定是最好的情况
*/
struct Node {
int d, val, pre;
int cnt;
}cur,now,q[65540];
int n;
int vis[65540];
char a[5];
int mcnt, tcnt,h;
string ans, tans;
void getans(int k) {
char c;
if (k == -1)return;
else {
getans(q[k].pre);
c = q[k].d + '0';
tans += c;
}
}
bool bfs(int k)
{
int i, j;
int head = 0, tail = -1;
memset(vis, 0, sizeof(vis));
//第一位数的情况
for (i = 1; i <= k; i++)
{
if (a[i])
{
cur.cnt = 0;
cur.d = a[i];
cur.pre = -1;
cur.val = a[i] % n;
vis[cur.val] = 1;
q[++tail] = cur;
}
}
int nval, ncnt,tval;
while (head <= tail)
{
now = q[head];
nval = now.val;
ncnt = now.cnt;
if (ncnt > mcnt)break;//当前求的数的位数已经大于以求的满足条件的数的位数了就不用在搜了
if (!nval)
{
h = head;
tcnt = ncnt;
return true;
}
for (i = 1; i <= k; i++)
{
tval = (nval * 10 + a[i]) % n;
if (!vis[tval])
{
vis[tval] = 1;
cur.cnt = ncnt + 1;
cur.d = a[i];
cur.pre = head;
cur.val = tval;
q[++tail] = cur;
}
}
head++;
}
return false;
}
int main() {
int flag;
while (cin >> n&&n) {
if (n >= 1 && n <= 9)
{
cout << n << endl;
continue;
}
flag = 0;
ans = "xx";//表示答案没找到
mcnt = 1000000000;//找到的数的位数
//枚举一个数的情况
for (int i = 1; i <= 9; i++)
{
a[1] = i;
if (bfs(1)) {
tans = "";
getans(h);
if (mcnt > tcnt || mcnt == tcnt&&ans > tans)
{
ans = tans;
mcnt = tcnt;
}
}
}
if (ans != "xx") {
flag = 1;
cout << ans << endl;
}
if (flag)continue;
//枚举两个数的情况
for (int i = 0; i <= 9; i++)
{
a[1] = i;
for (int j = i + 1; j <= 9; j++)
{
a[2] = j;
if (bfs(2))
{
tans = "";
getans(h);
if (mcnt > tcnt || mcnt == tcnt&&ans > tans)
{
ans = tans;
mcnt = tcnt;
}
}
}
}
cout << ans << endl;
}
return 0;
}