跳转链接
https://www.acwing.com/problem/content/1211/
题目描述
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
题解思路
直接参考https://www.acwing.com/solution/content/38879/
代码
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 15;
int n, ans;
bool st[N], backup[N];
bool check(int a, int c)
{
long long b = n * (long long)c - a * c; //把公式整理一下,然后先把b计算出来
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) //u表示我们已经用了多少个数字
{
if(u > 9) return; //如果我们把10个数字都用了的话,那就直接return了
if(check(a, c)) ans++; //如果满足要求,那我们判断一下a,c是否符合题目要求,如果符合,那么答案++
for(int i = 1; i <= 9; i++) //否则的话我们把c从1到9全部枚举一遍
if(!st[i])
{
st[i] = true;
dfs_c(u + 1, a, c * 10 + i); //如果这个数没用过,那么我们就把它放在c的后面,继续dfs下一层
st[i] = false;
}
}
void dfs_a(int u, int a)
{
if(a >= n) return;
if(a) dfs_c(u, a, 0); //如果这个数没用过,那么我们就把它放在c的后面,继续dfs下一层
for(int i = 1; i <= 9; i++) //如果这个数没用过,那么我们就把它放在c的后面,继续dfs下一层
if(!st[i])
{
st[i] = true;
dfs_a(u + 1, a * 10 + i); //如果这个数没有被用过,那么我们就加上它,并且dfs下一层
st[i] = false; //恢复现场,回溯一下
}
}
}
int main()
{
cin >> n;
dfs_a(0, 0); //第一个0表示我们已经用了多少个数字,后面那个0表示我们当前的a是多少
cout << ans << endl;
return 0;
}
