求一个数n的正整数倍m,在k进制下(poj 2238 只涉及10进制)表示时所需的不同数字数量最小
最后的答案不会有超过2个不同数字组成,理由如下:a,aa,aaa,aaaa,...中必定有两个模n同余(抽屉原理),两数相减就是n的倍数.接着判断只含一种数字能否满足答案,如果不行,再选2个数字进行广搜,找出最小的输出就可以了.
//poj 2283
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<map>
using namespace std;
const int maxn=65536;
int num[15];
int l,r,n;
int From[2*maxn],To[2*maxn],ans[2][2*maxn];
int flag[maxn];
int t;
int bfs(int a,int b)//广搜
{
memset(flag,0,sizeof(flag));
l=0,r=1;
if(a==0)
{
l=2;
To[2]=b;
r=3;
flag[0]=1;
From[2]=0;
}
while(l<r)
{
if(flag[To[l]]==1)
{
l++;
continue;
}
flag[To[l]]=1;
To[r]=(To[l]*10+a)%n;
From[r]=l;
if(To[r]==0)
break;
r++;
To[r]=(To[l]*10+b)%n;
From[r]=l++;
if(To[r]==0)
break;
r++;
}
int i;
if(l<r)
{
for(i=0;r!=0;i++)
{
if(r&1)
ans[t][i]=a;
else
ans[t][i]=b;
r=From[r];
}
return i-1;
}
return -1;
}
int main()
{
while(scanf("%d",&n),n)
{
num[0]=n;
int c=0;
for(int i=1;i<10;i++)
{
num[i]=1;
int j=i;
while(j%n!=0 && num[i]<n)
{
j=j*10%n+i;
num[i]++;
}
if(num[i]<num[c])
c=i;
}
if(c!=0)
{
for(int i=num[c];i>0;i--)
printf("%d",c);
printf("\n");
continue;
}
int m=n;
for(int i=0;i<10;i++)
{
for(int j=i+1;j<10;j++)
{
int ch=bfs(i,j);
if(ch<m && ch!=-1)
{
t=1-t;
m=ch;
}
else if(ch==m)
{
for(int i=ch;i>=0;i--)
{
if(ans[t][i]<ans[1-t][i])
{
t=1-t;
break;
}
else if(ans[t][i]>ans[1-t][i])
break;
}
}
}
}
for(int i=m;i>=0;i--)
printf("%d",ans[1-t][i]);
printf("\n");
}
return 0;
}
//hdu 4294
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<map>
using namespace std;
const int maxn=65536;
int num[15];
int l,r,n,k;
int From[2*maxn],To[2*maxn],ans[2][2*maxn];
int flag[maxn];
int t;
int bfs(int a,int b)
{
memset(flag,0,sizeof(flag));
l=0,r=1;
if(a==0)
{
l=2;
To[2]=b;
r=3;
flag[0]=1;
From[2]=0;
}
while(l<r)
{
if(flag[To[l]]==1)
{
l++;
continue;
}
flag[To[l]]=1;
To[r]=(To[l]*k+a)%n;
From[r]=l;
if(To[r]==0)
break;
r++;
To[r]=(To[l]*k+b)%n;
From[r]=l++;
if(To[r]==0)
break;
r++;
}
int i;
if(l<r)
{
for(i=0;r!=0;i++)
{
if(r&1)
ans[t][i]=a;
else
ans[t][i]=b;
r=From[r];
}
return i-1;
}
return -1;
}
int main()
{
while(~scanf("%d%d",&n,&k))
{
if(n==1)
{
printf("1\n");
continue;
}
num[0]=n;
int c=0;
for(int i=1;i<k;i++)
{
num[i]=1;
int j=i;
while(j%n!=0 && num[i]<n)
{
j=j*k%n+i;
num[i]++;
}
if(num[i]<num[c])
c=i;
}
if(c!=0)
{
for(int i=num[c];i>0;i--)
printf("%d",c);
printf("\n");
continue;
}
int m=n;
for(int i=0;i<k;i++)
{
for(int j=i+1;j<k;j++)
{
int ch=bfs(i,j);
if(ch<m && ch!=-1)
{
t=1-t;
m=ch;
}
else if(ch==m)
{
for(int i=ch;i>=0;i--)
{
if(ans[t][i]<ans[1-t][i])
{
t=1-t;
break;
}
else if(ans[t][i]>ans[1-t][i])
break;
}
}
}
}
for(int i=m;i>=0;i--)
printf("%d",ans[1-t][i]);
printf("\n");
}
return 0;
}