带分数|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;
}