题目标题: 100 可以表示为带分数的形式:100 = 3 + 69258 / 714
还可以表示为:100 = 82 + 3546 / 197
注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。 类似这样的带分数,100 有 11 种表示法。
以下代码列举所有表示法:
#include<stdio.h>
#include<string.h>
/*检查某个数是否出现重位的情况,可以与nKill整合,但这儿单独列出*/
bool checkNum(int n){
char arr[]="x123456789";
do{
if(arr[n%10]<='9'){
arr[n%10]='x';
}else{
return false;
}
n/=10;
}while(n!=0);
return true;
}
/*去除数组中已出现过的数字*/
void nKill(int n,char * arr){
do{
//标记已被选
arr[n%10]='#';
n/=10;
}while(n!=0);
}
/*交换两个数*/
void change(char *a,char *b){
char tmp;
tmp=*a;
*a=*b;
*b=tmp;
}
/*字符串逆序*/
void start2End(char * arr){
int len=strlen(arr),i;
for(i=0;i<len/2;i++){
change(arr+i,arr+len-i-1);
}
}
/*集合全排列*/
bool nextArr(char * arr,int len){
int i,j;
//寻找第一个左边比右边小的数
for(i=len-1;i>0;i--){
if(arr[i]>arr[i-1]){
break;
}
}
//如果找不到波动了,也就意味着找完了
if(i==0){
return false;
}
i--;
//寻找右边第一个比i处值大的
for(j=len-1;j>i;j--){
if(arr[j]>arr[i]){
break;
}
}
//交换
change(arr+i,arr+j);
//倒序
start2End(arr+i+1);
return true;
}
/*字符串转数字*/
int str2N(char *arr,int len){
int count=0,i=0;
while(i!=len){
count=count*10+(arr[i++]-'0');
}
return count;
}
/*遍历寻找填入/的位置*/
bool insert(char *res,int len,int result,int n){
int i,a,b;
for(i=len/2;i<len;i++){
a=str2N(res,i);
b=str2N(res+i,len-i);
//printf("%d/%d\n",a,b);
if(a/b==result && a%b==0){
printf("%d+%d/%d\n",n,a,b);
return true;
}
}
return false;
}
/*计算核心 作者:天之*/
void fun(int n,int result){
//1~9的全排列
char arr[]="#123456789";
char res[10];
nKill(n,arr);
int i=0,j=0;
char ch;
while((ch=arr[i++])!='\0'){
if(ch!='#'){
res[j++]=ch;
}
}
res[j]='\0';
do{
insert(res,j,result,n);
}while(nextArr(res,j));
}
void main(){
int i,n,tmp;
scanf("%d",&n);
for(i=1;i<n;i++){
tmp=n-i;
if(checkNum(tmp)){
fun(n-i,i);
}
}
}