问题描述
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
记:
题目的类型是:n = a + b/c,求满足的个数
一开始以为就是简单的两个不同比例的"数字+分数"模式,结果在测试其他数据时错误,
故将注意力放在a,b,c的比例分配(隐藏条件b >= c)
然而并没有发现规律...
上网查阅,有一篇博客讲到了全排序(http://blog.csdn.net/jopus/article/details/18998403)
还没开始精细阅读源码,被其中的分区的概念刺激
于是有了思路:
- a的默认比例为1,依次递增(a <= n的长度)
- 将区间总长度(LEN=9)减去a,并取得中值,从而得到b,c的值(b >= c)
- 每次dfs后,b ++,c --,再次dfs(当b-c > n的长度时,明显不符条件)
源码如下:
1 #include <stdio.h> 2 #define LEN 9 3 4 int n; 5 int a,b,c; 6 int sum = 0 , len = 0; 7 int ans[LEN+1] = {0}; 8 int num[LEN+1] = {0,1,2,3,4,5,6,7,8,9,}; 9 int f[LEN+1] = {0}; 10 11 void dfs(int x) 12 { 13 int i , j; 14 int x1,x2,x3; 15 if (x > 9) 16 { 17 x = x1 = x2 = x3 = 0; 18 /*1.确定第一个值x1*/ 19 for (i = 0 , j = 1 ; i < a ; i ++) 20 { 21 x1 += ans[++x]*j; 22 j *= 10; 23 } 24 25 /*2.确定分数的分子x2*/ 26 for (i = 0 , j = 1 ; i < b ; i ++) 27 { 28 x2 += ans[++x]*j; 29 j *= 10; 30 } 31 32 /*3.确定分数的分母x3*/ 33 for (i = 0 , j = 1 ; i < c ; i ++) 34 { 35 x3 += ans[++x]*j; 36 j *= 10; 37 } 38 39 if (x2%x3 == 0 && (x1 + x2/x3) == n) 40 { 41 sum ++; 42 //printf("%d+%d/%d\n",x1,x2,x3); 43 } 44 return ; 45 } 46 47 for (i = 1 ; i <= 9 ; i ++) 48 { 49 if (!f[i]) 50 { 51 ans[x] = num[i]; 52 f[i] = 1; 53 dfs(x+1); 54 f[i] = 0; 55 } 56 } 57 58 return ; 59 } 60 61 int main(void) 62 { 63 int i; 64 scanf("%d",&n); 65 i = n; 66 while(i) 67 { 68 i = i/10; 69 len ++; /*获取n的长度*/ 70 } 71 72 for (a = 1 ; a <= len ; a ++) 73 { 74 i = LEN-a; 75 b = i - i/2; 76 c = i - b; 77 if (b < c)/*b必定为较大区间*/ 78 { 79 b = b^c; 80 c = b^c; 81 b = b^c; 82 } 83 84 /*更改b和c的比例*/ 85 while (c) 86 { 87 dfs(1); 88 b ++; 89 c --; 90 } 91 } 92 printf("%d",sum); 93 return 0; 94 }