带分数

   带分数

问题描述

100 可以表示为带分数的形式:100 = 3 + 69258 / 714

 

还可以表示为:100 = 82 + 3546 / 197

 

注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。

 

类似这样的带分数,100 有 11 种表示法。

 

输入格式

从标准输入读入一个正整数N (N<1000*1000)

输出格式

 

程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。

 

注意:不要求输出每个表示,只统计有多少表示法!

 

样例输入1

100

样例输出1

11

样例输入2

105

样例输出2

6


#include "stdio.h" 
#include "string.h"
const int Max = 9;
int n,right_length,cnt,n_right;
int flag[10];
int bak[10];
 void dfs(int depth,int v);
 int checks(int n);
 int check(int l); 
 
int check(int l){                     //标记已有的位,检查数字是否符合规则
    int length = 0;
    while(l){
        if(flag[l%10])return 0;
        flag[l%10] = 1;
        l /= 10;
        length ++;
    }
    right_length = Max - length;
    return 1;
}
 
 //由于每次实验分母都需要验证,而整数不懂,所以需要checks函数,检测分母是否符合规则 
int checks(int n){
    int length = 0;
    memcpy(bak,flag,sizeof(bak));
    while(n){
        if(bak[n%10])return 0;
        bak[n%10] = 1;
        n /= 10;
        length ++;
    }
    return length;
}

 /*深度优先枚举分母,分子=right*分母*/
void dfs(int depth,int v){                 //depth表示分母长度     
//通过剩余数字构造分子,并且验证分母
   if(depth <= right_length/2){    //分母只能为一半长度最多 否则除不尽 
        if(checks(v * n_right) == right_length - depth){
          //  printf("%d = %d + %d/%d\n",n,n-n_right,v*n_right,v);
            cnt ++;
        }
        int i;
        for(i = 1 ; i <= Max ; i ++){
            if(flag[i])continue;
            flag[i] = 1;
            dfs(depth + 1,v * 10 + i);
            flag[i] = 0;
        }
    }
}
 
int main(){
    while(scanf("%d",&n) == 1){		
        cnt = 0;
        int left;
        for(left = 1 ; left < n ; left ++){
            flag[0] = 1;       //0不算 所以先标志占用 
            if(check(left)){    //检查左边是不是符合要求,并标志已用数字和长度 
                n_right = n- left;
                dfs(0,0);
            }
            memset(flag,0,sizeof(flag));   //将flag标志初始化 
        }
        printf("%d\n",cnt);
    }
    return 0;
}


你可能感兴趣的:(带分数)