链接
http://acm.hdu.edu.cn/showproblem.php?pid=1664
题解
通过写一些暴力,就容易得出这样的猜测:答案是不是最多包含两种数字?
事实的确实这样的,随便用某个数位
x
x
x,写出
x
,
x
x
,
x
x
x
,
x
x
x
x
,
x
x
x
x
x
,
.
.
.
,
x
x
x
.
.
.
x
x
x
x
x,xx,xxx,xxxx,xxxxx,...,xxx...xxxx
x,xx,xxx,xxxx,xxxxx,...,xxx...xxxx这样写
n
+
1
n+1
n+1个,根据鸽巢原理,肯定存在两个数关于
n
n
n同余,那么它们的差就肯定是
n
n
n的倍数,而这个数只包含
0
0
0和
x
x
x两种数位,所以肯定存在一个有包含两种数位的答案。
先判断有没有只包含一种数位的答案
直接能想到的就是构造数位
x
x
x,然后判断
x
,
x
x
,
x
x
x
.
.
.
x,xx,xxx...
x,xx,xxx...是不是模
n
n
n余
0
0
0,然而枚举到多少位呢?
仔细考虑这个过程,我们是用一个临时变量
t
m
p
tmp
tmp,存储当前数字对
n
n
n的余数,然后tmp = tmp*10+x
注意到,如果
t
m
p
tmp
tmp和之前重复出现了,那么肯定就面临一个循环节,也就是说后面的操作都和之前重复了,因此没必要再枚举下去,而
t
m
p
tmp
tmp的所有取值的可能就只有
n
n
n种,因此我可以一发现循环就直接退出,这样复杂度最坏也只是
O
(
n
)
O(n)
O(n)
考虑包含两种数位的答案
假设两种数位是
x
,
y
x,y
x,y
我还是用一个
t
m
p
tmp
tmp表示一个由
x
x
x和
y
y
y写成的数字对
n
n
n的余数
和之前不同的是,一个
t
m
p
tmp
tmp又会延伸出两种选择
这个时候我们需要
B
F
S
BFS
BFS,这样能够保证我们搜出来的是最小的
开一个访问标志数组,存储一下这个余数出现过没有,因为是
B
F
S
BFS
BFS所以后出现的肯定不如前出现的更优
这样复杂度依然是
O
(
n
)
O(n)
O(n)
代码
//数论、搜索
#include <bits/stdc++.h>
#define maxn 70000
#define ll long long
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
ll q[maxn], head, tail, pre[maxn], N, dig[2], d[maxn];
bool vis[maxn];
ll read(ll x=0)
{
ll c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-48;
return f*x;
}
ll BFS(ll k)
{
ll i, x, tmp;
head = tail = 1;
cl(vis), cl(pre);
for(i=0;i<k;i++)if(dig[i])d[tail] = dig[i], q[tail++]=dig[i]%N, vis[dig[i]%N]=true;
while(head<tail)
{
x = q[head++];
if(x==0)return head-1;
for(i=0;i<k;i++)
{
tmp = (x*10+dig[i])%N;
if(!vis[tmp])
{
vis[tmp] = true;
pre[tail] = head-1;
d[tail] = dig[i];
q[tail++] = tmp;
}
}
}
return -1;
}
string get_string(ll last)
{
string ans = "";
for(ll p = last;p;p=pre[p])
{
ans += char(0x30+d[p]);
}
reverse(ans.begin(),ans.end());
return ans;
}
int main()
{
ll i, j, rax;
string ans, tmp;
while(N = read())
{
ans = "-1";
for(i=1;i<=9;i++)
{
dig[0] = i;
rax = BFS(1);
if(rax != -1)
{
tmp = get_string(rax);
if(ans == "-1")ans = tmp;
else if(ans.size()>tmp.size())ans = tmp;
}
}
if(ans == "-1")
{
for(i=0;i<=9;i++)for(j=i+1;j<=9;j++)
{
dig[0] = i, dig[1] = j;
rax = BFS(2);
if(rax != -1)
{
tmp = get_string(rax);
if(ans == "-1")ans = tmp;
else if(ans.size()>tmp.size() or ans.size()==tmp.size() and ans>tmp)ans = tmp;
}
}
}
cout << ans << endl;
}
return 0;
}