稳定的数字
Time Limits: 1000 ms Memory Limits: 65536 KB
Description
定义一种操作,经过该操作,可以得到一个数中所有数字的乘积(原数至少要是个两位数)。比如679经过一次操作可以得到378。 你的任务读入一个数,计算经过一次操作得到它的最小的数是多少。
Input
仅一行,表示一个十进制数。数的长度可能到达1000位。
Output
经过一次操作可以得到这个数的最小的数。如果没有这样的数,输出“There is no such number.”(不包括引号)
Sample Input
Input1:
0
Input2:
18
Input3:
51
Sample Output
Output1:
10
Output2:
29
Output3:
There is no such number.
解题思路
其实很简单,这道题主要考的是高精度除以单精度,不用多说了吧。
如果这个数是一位数,输出加10,其他的直接从9到2枚举再作除法,倒过来输出就可以了。
如果你怕会超时的话,那就压位(状态压缩)吧。
const
maxn=1000000000000000000;
var
c:char;
a:array[1..4000]of int64;
num,b:array[0..4000]of int64;
ten:array[0..18]of int64;
n,i,top,tot,j:longint;
q:boolean;
function can(v:longint):boolean;
var x,i:longint;
begin
x:=0;
if(top=1)and(b[top]=0) then exit(false);
for i:=top downto 1 do
begin
num[i]:=(x*maxn+b[i])div v;
x:=(x*maxn+b[i])mod v;
end;
if x<>0 then exit(false);
b:=num;
while(top>1)and(b[top]=0)do dec(top);
exit(true);
end;
{Main}
begin
assign(input,'number.in'); reset(input);
assign(output,'number.out'); rewrite(output);
read(c);
while c in['0'..'9'] do
begin inc(n);num[n]:=ord(c)-48;read(c);end;
if n=1 then
begin writeln(num[n]+10);halt;end;
b[0]:=maxn;
ten[0]:=1;
for i:=1 to 18 do ten[i]:=ten[i-1]*10;
for j:=n downto 1 do
begin
i:=n-j+1;
if i mod 18=1 then inc(top);
b[top]:=b[top]+num[j]*ten[(i-1) mod 18];
end;q:=true;
for i:=9 downto 2 do
begin
while can(i) do
begin inc(tot);a[tot]:=i;end;
if(top=1)and(b[1]=1) then
begin q:=false;break;end;
end;
if q then
begin writeln('There is no such number.');halt;end;
for i:=tot downto 1 do
if a[i]<>0 then write(a[i]);
end.
#include<cstdio>
#include<cstring>
#define fo(i,x,y) for(int i=x;i<=y;i++)
#define min(x,y) ((x)<(y)?(x):(y))
using namespace std;
int Find(int,int);
int n,Fx[8][2]={{1,2},{-1,2},{1,-2},{-1,-2},{2,1},{-2,1},{2,-1},{-2,-1}},x[11],y[11];
int F[11][11][11][1024],k,dist[11][11],ans=0x7fffffff,data[401][3];
bool pd[21][21];
int main()
{
scanf("%d%d",&n,&k);
fo(i,1,k)
{
scanf("%d%d",&x[i],&y[i]);
fo(j,1,i-1){dist[i][j]=dist[j][i]=Find(i,j);}
}
memset(F,0x7f,sizeof(F));
fo(i,1,k)F[i][1][i][1<<(i-1)]=0;
fo(s,1,k)fo(i,2,k)fo(j,1,k)fo(l,1,(1<<k)-1)if((l & (1<<(j-1)))>0)fo(o,1,k)if(o!=j && (l & (1<<(o-1)))>0)
{F[s][i][j][l]=min(F[s][i][j][l],F[s][i-1][o][l^(1<<(j-1))]+dist[j][o]);}
fo(i,1,k)fo(j,1,k){ans=min(ans,dist[i][j]+F[i][k][j][(1<<k)-1]);}
printf("%d",ans);
}
int Find(int h,int t)
{
int H=0,T=1,x1,y1,xx,yy,s;
memset(pd,false,sizeof(pd));
data[1][0]=x[h];data[1][1]=y[h];data[1][2]=0;
pd[x[h]][y[h]]=true;
while(H<T)
{
x1=data[++H][0];y1=data[H][1];s=data[H][2];
fo(o,0,7)
{
xx=x1+Fx[o][0];yy=y1+Fx[o][1];
if(xx<1 || xx>n || yy<1 || yy>n)continue;
if(pd[xx][yy])continue;
if(xx==x[t] && yy==y[t])return(s+1);
pd[xx][yy]=true;
data[++T][0]=xx;data[T][1]=yy;data[T][2]=s+1;
}
}
}