题目描述
100 可以表示为带分数的形式:$100 = 3 + \frac {69258}{714}$
还可以表示为:$100 = 82 + \frac {3546}{197}$
注意特征:带分数中,数字 $1∼9$分别出现且只出现一次(不包含 $0$)。
类似这样的带分数,$100$有 $11$ 种表示法。
输入格式
一个正整数。
输出格式
输出输入数字用数码 $1∼9$ 不重复不遗漏地组成带分数表示的全部种数。
数据范围
$1≤N<10^6$
输入样例1:
100
输出样例1:
11
输入样例2:
105
输出样例2:
6
dfs暴力搜索
直接枚举每一种排列,然后双重循环枚举分界点,将排列分为三部分,求出结果
可以看出,如果第一个数已经大于给定的值,即可及时break掉减少一层循环
时间复杂度
$O(n!×n)$
C++ 代码
#include <iostream>
using namespace std;
int n;
const int N = 10;
int a[N];
bool st[N];
int res = 0;
int cal(int l,int r) {
int ans = 0;
for(int i = l;i <= r;i ++) ans = ans * 10 + a[i];
return ans;
}
void dfs(int u) {
if(u > 9) {
for(int i = 1;i < 9;i ++) {
int a = cal(0,i);
if(a >= n) break;
for(int j = i + 1;j <= 9;j ++) {
int b = cal(i + 1,j);
int c = cal(j + 1,9);
if(a * c + b == n * c) res ++;
}
}
}
for(int i = 1;i <= 9;i ++) {
if(!st[i]) {
st[i] = true;
a[u] = i;
dfs(u + 1);
st[i] = false;
}
}
}
int main()
{
cin >> n;
dfs(1);
cout << res << endl;
return 0;
}
优化
只需要枚举$a$和$c$,根据$b = c × n - a × c$求出b即可,然后判断b的每一位是否都有用到
那么我们可以嵌套递归,对于$a$的每一个分支,都递归求出$c$
C++ 代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 20;
bool st[N], backup[N];
int n;
int ans;
bool check(int a,int c) {
int b = n * c - a * c;
if(!a || !b || !c) return false;
memcpy(backup,st,sizeof st);
while(b) {
int x = b % 10;
b /= 10;
if(!x || backup[x]) return false;
backup[x] = true;
}
for(int i = 1;i <= 9;i ++)
if(!backup[i]) return false;
return true;
}
void dfs_c(int u,int a,int c) {
if(u > 9) return;
if(check(a,c)) ans ++;
for(int i = 1;i <= 9;i ++) {
if(!st[i]) {
st[i] = true;
dfs_c(u + 1,a,c * 10 + i);
st[i] = false;
}
}
}
void dfs_a(int u,int a) {
if(a > n) return;
if(a) dfs_c(u,a,0);
for(int i = 1;i <= 9;i ++) {
if(!st[i]) {
st[i] = true;
dfs_a(u + 1,a * 10 + i);
st[i] = false;
}
}
}
int main()
{
cin >> n;
dfs_a(0,0);
cout << ans << endl;
return 0;
}