100 可以表示为带分数的形式:100 = 3+69258 / 714
还可以表示为:100 = 82+3546 / 197
注意特征:带分数中,数字 1∼9 分别出现且只出现一次(不包含 0)。
类似这样的带分数,100 有 11 种表示法。
输入格式
一个正整数。
输出格式
输出输入数字用数码 1∼9 不重复不遗漏地组成带分数表示的全部种数。
数据范围
1≤N<10^6
输入样例1:
100
输出样例1:
11
输入样例2:
105
输出样例2:
6
思路: 暴力求出1 - 9 的全排列方案,共9! = 362880 个
然后对每一种全排列进行拆分成3段,进行验证满不满足带分数的形式。 注意一点: n = a + b / c 可将除式转换成相乘相加的形式 n * c = a * c + b 因为除法运算当数字比较大的时候,可能会出现精度问题。
由于是将一个全排列分成3段,因此各段之间一定是不会有重复元素的,且1 - 9 一定会全部被用上。
#include<iostream>
#include<cmath>
#include<vector>
using namespace std;
int vis[10];
int n,cnt;
vector<vector<int>> p;
vector<int> pro = vector<int>(10);
void dfs(int u){
if (u > 9){
p.push_back(pro);
return;
}
for (int i = 1 ; i <= 9; ++i){
if(!vis[i]){
vis[i] = 1;
pro[u] = i;
dfs(u + 1);
vis[i] = 0;
}
}
}
int get_base(int index,int base_num){
int sum = 0;
for (int i = 1; i <= base_num; ++i)
sum = sum*10 + p[index][i];
return sum;
}
int get_fm(int index,int base_num,int fm_num){
int sum = 0;
for (int i = base_num + 1; i <= base_num + fm_num; ++i){
sum = sum * 10 + p[index][i];
}
return sum;
}
int get_fz(int index,int pre_num){
int sum = 0;
for (int i = pre_num + 1; i <= 9; ++i){
sum = sum * 10 + p[index][i];
}
return sum;
}
int main(){
cin>>n;
dfs(1);
for (int i = 0; i < p.size(); ++i){
for (int j = 0 ;j < 7; ++j){ // 总共有9位,其中base 最多7位,因为分数中的分子和分母至少要有一位。
int base = get_base(i,j + 1);
int base_num = j + 1;
for (int k = 1; k < 9 - base_num; ++k){ // k 不能等于 9 - base_num 至少要给分子留一位
int fm = get_fm(i,base_num,k);
int fm_num = k;
int fz = get_fz(i,base_num + fm_num);
// cout<<base<<" "<<fm<<" "<<fz<<endl;
if (base * fm + fz == n*fm) cnt++; // 转换成相乘相加的形式
}
}
}
cout<<cnt<<endl;
return 0;
}