7 15 16 101 0
7 555 16 1111
给一个n,让你找出含不同数字最少的n的倍数,如果含不同数字相同,则输出最小的。
开始还真不知道咋个做,然后就网上找呀找,结果网上就说了:
对于任意的整数 n ,必然存在一个由不多于两个的数来组成的一个倍数。 因为 a ,aa , aaa…… 取 n+1 个,则由鸽笼原理,必有两个模 n 余数相同,相减即得 n 的倍数 m 。而 m 只由 a 、 0 组成。
这样一下就简单了,因为是不同数字最少优先,所以先扫描一位的所以情况,然后在考虑两位的情况。这道题数据有点打,开始没用string,用的char,结果需要把数组开得很大,但是这样对于大部分数据来说就是浪费空间,导致了在队列操作时花费很多时间,然后TLE了,后来改成string,还是不行,当初我把搜1位和两位融合在了一起,但是做的不好,后来还是分开了,这样效率要高很多。
总结一句:题其实很简单。
-
#include <iostream>
#include <stdio.h>
#include <queue>
#include <string.h>
using namespace std;
#define maxsize 65540
bool vis[65540];
int num[2],n;
struct node
{
string s;
int r;
int len;
node()
{
s="";
r=0;
len=0;
}
}ans;
bool Find()
{
ans.s="";
for (int i=1; i<=9; i++)
{
node temp;
temp.s+=(i+'0');
temp.r=i%n;
while (temp.s.size()<=65536 && temp.r!=0)//余数最多有65536个(n<=65536)
{
temp.s+=(i+'0');
temp.r=(temp.r*10+i)%n;
}
if(temp.r==0)
{
if(ans.s.length()==0 ||(ans.s.length()>temp.s.length()))
ans=temp;
else if(ans.s.length()==temp.s.length() && ans.s>temp.s)
ans=temp;
}
}
if(ans.s.length())
{
cout<<ans.s<<endl;
return true;
}
return false;
}
void bfs()
{
for (int i=0; i<=n; i++)
vis[i]=false;
queue<node>q;
node a,temp;
for (int i=0; i<2; i++)
{
if(num[i]>0)
{
a.s=num[i]+'0';
a.r=(a.r*10+num[i])%n;
a.len=a.s.length();
vis[a.r]=1;
q.push(a);
a.s="";
a.r=0;
}
}
while (!q.empty())
{
a=q.front();
q.pop();
for (int i=0; i<2; i++)
{
temp=a;
temp.s+=num[i]+'0';
temp.len=temp.s.length();
if((ans.len!=0 &&ans.len<temp.len)|| (ans.len==temp.len &&ans.s<temp.s))//剪枝
return;
temp.r=(temp.r*10+num[i])%n;
if(!vis[temp.r])
{
vis[temp.r]=1;
if(temp.r==0)
{
if(ans.len==0)
ans=temp;
else if(ans.len >temp.len)
ans=temp;
else if(ans.len==temp.len&&ans.s>temp.s)
ans=temp;
return;
}
q.push(temp);
}
}
}
}
int main()
{
while (scanf("%d",&n) &&n)
{
if(n/10==0)
{
printf("%d\n",n);
continue;
}
if(!Find())
{
ans.s="";
ans.len=0;
for (int i=0; i<=9; i++)
{
for (int j=i+1; j<=9; j++)
{
num[0]=i;
num[1]=j;
bfs();
}
}
cout<<ans.s<<endl;
}
}
return 0;
}