带分数|2013年蓝桥杯B组题解析第九题-fishers

带分数

100 可以表示为带分数的形式:100 = 3 + 69258 / 714
还可以表示为:100 = 82 + 3546 / 197
注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。
类似这样的带分数,100 有 11 种表示法。
题目要求:
从标准输入读入一个正整数N (N<1000*1000)
程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部种数。
注意:不要求输出每个表示,只统计有多少表示法!
例如:
用户输入:
100
程序输出:
11

再例如:
用户输入:
105
程序输出:
6
资源约定:
峰值内存消耗 < 64M
CPU消耗 < 3000ms

思路:dfs全排列 + 筛选数据,这里的筛选数据方法是:枚举两个端点,也就是分成三个区间判断 a + b/c 是否等于 输入的数n。

代码:

#include<iostream>
using namespace std;

//dfs搜索全部组合,最后筛选满足条件的组合 

int x = 0,  count = 0;
int visited[10];
int ans = 0;
int n;


//将数组区间转化为数字 
int getNum(int list[], int f, int r)  
{  
    int i = 0, num = 0;  
    for (i = f; i <= r; i++)   
        num = list[i] + num * 10; //进位 
    return num;  
}

//筛选出正确的数据: 划分成三个区间 a + b/c (也就等于枚举两个端点) 
int test(int a[]){
	int t = 0;
//	a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i
	//枚举左端点 
	for(int i=1;i<=x;i++){
		double x = 0;
		double y = 0;
		double z = 0;
		//枚举右端点 
		for(int j=i+1;j<9;j++){
			int k1 = i+1;
			int k2 = j+1;
			//求值 
			x = getNum(a,1,k1-1);
			y = getNum(a,k1,k2-1);
			z = getNum(a,k2,9);
			if((y/z) + x == n){
				t++;
			}
		}
	}
	return t;
}

//搜索 全排列 
void dfs(int k,int a[]){
	if(k == 10){
		int tt = test(a);
		if(tt){
			ans+=tt;
		}
		return;
	}
	
	for(int i=1;i<=9;i++){
		//是否使用i这个数:当没有使用过i这个数的值时 就可以用这个数了 
		if(!visited[i]){
			a[k] = i;
			visited[i] = 1; //标记这个数已经用过 
			dfs(k+1,a);
			a[k] = 0; //回溯 
			visited[i] = 0; //回溯标记这个数没有用过 
		}
	}
}

int main(){
	cin>>n;
	int temp = n;
	//统计n总共多少位: 便于dfs的剪枝 
	while (temp != 0)      
    {  
        ++x;  
        temp /= 10;  
    }
	int a[10];
	for(int i = 1;i<=9;i++){
		visited[i] = 0;
	}
	dfs(1,a);
	cout<<ans<<endl;
}

方法二:用algorithm的全排列函数,自己写字符串截取函数(库函数substr效率很低!开辟字符串,拷贝到新空间)

#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <string>

using namespace std;

int parse(const char *arr, int pos, int len) {
    int ans = 0;
    int t = 1;
    for (int i = pos + len - 1; i >= pos; --i) {
        ans += (arr[i] - '0') * t;
        t *= 10;
    }
    return ans;
}

int main(int argc, const char *argv[]) {
    int n, ans = 0;
    scanf("%d", &n);
    std::string s = "123456789";
    do {
        const char *str = s.c_str();
        for (int i = 1; i <= 7; ++i) {
//            string a = s.substr(0, i);
            int inta = parse(str, 0, i);
            if (inta >= n)break;

            for (int j = 1; j <= 9 - i - 1; ++j) {
//                string b = s.substr(i, j);
//                string c = s.substr(i + j)
//                int intb = atoi(b.c_str());
//                int intc = atoi(c.c_str());
                int intb = parse(str, i, j);
                int intc = parse(str, i + j, 9 - i - j);
                if (intb % intc == 0 && inta + intb / intc == n)ans++;
            }
        }
    } while (std::next_permutation(s.begin(), s.end()));
    printf("%d\n", ans);
    return 0;
}
posted @ 2019-01-27 15:18  fishers  阅读(371)  评论(0编辑  收藏  举报