原题链接:acwing.带分数
100 可以表示为带分数的形式: 100 = 3 + 69258 714 100 = 3 + \frac {69258}{714} 100=3+71469258
还可以表示为: 100 = 82 + 3546 197 100 = 82 + \frac {3546}{197} 100=82+1973546
注意特征:带分数中,数字 1 ∼ 9 1∼9 1∼9分别出现且只出现一次(不包含 0 0 0)。
类似这样的带分数, 100 100 100有 11 11 11 种表示法。
一个正整数。
输出输入数字用数码 1 ∼ 9 1∼9 1∼9 不重复不遗漏地组成带分数表示的全部种数。
1 ≤ N < 1 0 6 1≤N<10^6 1≤N<106
100
11
105
6
直接枚举每一种排列,然后双重循环枚举分界点,将排列分为三部分,求出结果
可以看出,如果第一个数已经大于给定的值,即可及时break掉减少一层循环
O ( n ! × n ) O(n!×n) O(n!×n)
#include
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 a a和 c c c,根据 b = c × n − a × c b = c × n - a × c b=c×n−a×c求出b即可,然后判断b的每一位是否都有用到
那么我们可以嵌套递归,对于 a a a的每一个分支,都递归求出 c c c
#include
#include
#include
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;
}