题目:Division
题意:输入正整数n,按从小到大的顺序输出所有形如abcde/fghij = n的表达式,其中a~j恰好为数字0~9的一个排列(可以有前导0),2≤n≤79。
思路:如果分别枚举abcde 和 fghij 是 10!= 3628800
题中已已知商n,所以我们只需枚举除数fghij 即可得出 被除数abcde 。
(1)枚举:利用dfs进行0~9中枚举5位数,
(2)拆分:将枚举的除数和计算得的被除数进行位数拆分,利用标记数组看是否10个数字都出现且不重复,计算除数和被除数的位数和 >10(因为再枚举会越大,永远不符合规则了。)时停止枚举!
参考:入门经典-例7-1-P182
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int visit[10],n,flag[10],sign,prt;
int mark(int value){//拆分数
int cot = 0;//记录不重复数字
if(value < 10000){//小于5位数将前置0补上!
flag[0] = 1;cot++;
}
while(value){//拆分数字
flag[value%10] = 1;//标记每一位上的数字,用于判断是否重复
value /= 10;
cot++;
}
return cot;}//返回数的位数
bool judge(int a,int b){//判断是否符合规则
memset(flag,0,sizeof(flag));//用于标记不重复数字
if(mark(a)+mark(b) > 10) {sign = 1; return false;}//超出10位,不符合
for(int i=0;i<10;i++){
if(!flag[i]) return false;//没有出现10位数中的某位,不符合
}
return true;}
void dfs(int steps,int res){//递归枚举除数
if(steps == 5){
int temp = res*n;//被除数 = 除数*商
if(judge(temp,res))//将被除数和除数进行是否符合规则,符合输出
{ printf("%05d / %05d = %d\n",temp,res,n);prt = 0;}
return;
}
for(int i=0;i<=9;i++){
if(sign) break;//当被除数和除数的位数和大于10时不再枚举
if(visit[i] == 0){
visit[i] = 1;
dfs(steps+1,res*10+i);
visit[i] = 0;
}
}
}
int main()
{
int k = 0;
while(scanf("%d",&n)!=EOF && n){
if(k)printf("\n");k++;
memset(visit,0,sizeof(visit));
sign = 0;prt = 1;
dfs(0,0);
if(prt) printf("There are no solutions for %d.\n",n);
}
return 0;
}