带分数(穷举法) 蓝桥杯赛题

问题描述(蓝桥杯练习系统可提交)

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
 
本人解题思路(还有其他):枚举法
既然是由不同数字组成的,那么可以初始化一个数组[1,2,3,4,5,6,7,8,9],然后对这个数组进行全排列。对于前面每一个排列组合,把它切成三份,a,b,c,然后再去拿去a,b,c的每一种组合数。
比如,此时的全排列数组为[3,6,9,2,5,8,7,1,4],  首先为a取值,假如a = 3(当然a还可以取36,369...,前提是a不能大于等于n), 那么b,c的取值可以这样取,从3之后开始,在他们任意之间插入“/”, “/”前面的就是b,后面的就是c,在a,b,c得每一次取值都去验证a+b/c==n, 是,就+1.
 
当获取到一个排列时(我是用的next_permutation()函数获取得),可得
当a=3时,b,c可取6/9258714,69/258714,692/58714...  
当a=36时,b,c可取9/258714,92/58714,925/8714...
当a=369时,b,c可取2/58714,25/8714,258/714..(如果n=100,那么此时a的取值是错误的)
......
 
细节:c不能为0
 
 
#include <iostream>
#include <algorithm>

using namespace std;

// 拿数字 
int toNum(int *data,int s, int e) {
    int ret = 0;
    for (int i = s; i <= e; i++) {
        ret = ret*10+data[i];
    }
    return ret;
}

int main() {
    int data[10];
    int n, ans,s,e,a,b,c,flag;
    while(~scanf("%d", &n)) {
        for (int i = 0; i < 10; i++) data[i] = i;
        ans = 0;
        do {
            s = e = 1;
            while(1) {
                a = toNum(data, s, e);// 确定a得值 
                if (a >= n) break; // 当a截取得值大于n时,说明已经是错误得,直接进行下一个排列 
                // 让分数线从左往右一位数一位数的移动 
                for (int i = e+1; i < 10-1; i++) {// 必须保证c有一位数,不然分母为零,所以i<10-1 
                    b = toNum(data, e+1, i);
                    c = toNum(data, i+1, 9);
                    if (b%c != 0) continue;
                    if (a+b/c==n)  ans++;
                }
                e++;// 移动 
            }
        }while(next_permutation(data+1, data+10));    // 全排列 
        cout << ans << endl;
    }
    return 0;
}

此处无声胜有声。

 
 
 
原文地址:https://www.cnblogs.com/hello-dummy/p/12178757.html