题目大意:
输入两个正整数x,y,判断x和y能否由1到100之间的整数乘积组成,数字不能重复使用。
分析:
想不到很好的方法,一般考虑用搜索来解决。
最初的时候没有考虑到数据范围。稍加分析,x,y最大可以达到100!,大约160位,只能使用高精度运算。
搜索核心如下:
void perform(bigNum x,int m) //对于大数x,用不大于m的整数去试除
{
if(x等于1) {
//成功, 标记变量
return;
}
for( p=m ; p>1 ; p-- ) //搜索
if( p没有用过 && p能整除x ){
标记p为使用过;
perform( x/p , p-1 ); //向下递归
取消p的标记;
}
}
一次性AC,时间0.04s
=============================================
/*
ZJU1003 Crashing Balloon
搜索+大数除小数
*/
#include <stdio.h>
#include <string.h>
#define clr(a) memset(a,0,sizeof(a))
#define N 205
typedef struct{
int a[N];
int len;
}bigNum;
//Vars
bigNum X,Y,One;
int e[N];
int player,achive,uphold;
//Functions
int s2a(char s[],bigNum *b){
int n,i;
n=strlen(s);
for(i=0;i<n;i++){
b->a[n-i-1]=s[i]-'0';
}
return n;
}
int input(){
char x[N+N],y[N+N];
if(scanf("%s%s",x,y)==EOF) return 0;
X.len=s2a(x,&X);
Y.len=s2a(y,&Y);
return 1;
}
void printb(bigNum b){
int i;
for(i=b.len-1;i>=0;i--)
printf("%d",b.a[i]);
printf("/n");
}
int cmp(bigNum x,bigNum y){
int i;
if(x.len!=y.len) return x.len-y.len;
for(i=x.len-1;i>=0;i--){
if(x.a[i]!=y.a[i]) return x.a[i]-y.a[i];
}
return 0;
}
void cpy(bigNum *x,bigNum *y){
int i;
x->len=y->len;
for(i=0;i<y->len;i++) x->a[i]=y->a[i];
}
/*
division
z = x/y
return x%y
*/
int div(bigNum *x,int y,bigNum *z){
int i,n,r;
n=x->len;
for(r=0,i=n-1;i>=0;i--){
r=r*10+x->a[i];
z->a[i]=r/y;
r%=y;
}
while(n>1&&!z->a[n-1]) n--;
z->len=n;
return r;
}
//Perform
void perform(bigNum x,int m){
bigNum y;
int i,p,r;
if(!cmp(x,One)){
if(player){
uphold=1;
player=0;
perform(Y,100);
player=1;
}
else{
achive=1;
}
return;
}
for(p=m;p>1;p--){
r=div(&x,p,&y);
if(!e[p]&&!r){
e[p]=1;
perform(y,p-1); //next
e[p]=0;
}
if(achive) return;
}
return;
}
//Main
int main()
{
int i,j,k,m,n;
bigNum Tmp;
One.len=1;
One.a[0]=1;
while(input()){
if(cmp(X,Y)>0){
cpy(&Tmp,&X);cpy(&X,&Y);cpy(&Y,&Tmp);
}
clr(e);
player=1; uphold=achive=0;
if(!(X.len>=160||Y.len>160))
perform(X,100);
if(uphold==achive) printb(Y);
else printb(X);
}
return 0;
}