题目
100100 可以表示为带分数的形式:100=3+69258714100=3+69258714
还可以表示为:100=82+3546197100=82+3546197
注意特征:带分数中,数字 1∼91∼9 分别出现且只出现一次(不包含 00)。
类似这样的带分数,100100 有 1111 种表示法。
输入格式
一个正整数。
输出格式
输出输入数字用数码 1∼91∼9 不重复不遗漏地组成带分数表示的全部种数。
数据范围
1≤N<1061≤N<106
输入样例1:
100
输出样例1:
11
输入样例2:
105
输出样例2:
6
这道题可以直接暴力求解,然后对暴力求解进行优化,然后就得出不是那么暴力的求解方法
将整数,分子,分母,分别当作 a b c ;
输入的数是n ,所以可以根据 a c 求解出 b 的值,然后在判断是否符合题意。
- 进行第一个dfs ,求出 a 的各种情况
- 根据 a 的各种情况,进行第二个dfs ,求出 c 的情况
- 通过 求出的 a c 的值,求解b ,并且判断是否符合题意
注意:check 函数 要在 dfs_c 上面 ,dfs_c 要在 dfs_a 前面,否则会出现编译错误
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 520;
int n;
int had_use[N],ever[N]; // 两个数组分别判断该数字是否使用过
int ans = 0;
bool check(int a,int c)
{
int b = n*c - a*c;
if(!a || !b || !c) return false;
memcpy(ever,had_use,sizeof had_use);
while(b)
{
int t = b % 10;
b /= 10;
if(ever[t] || !t) return false;
ever[t] = 1;
}
for(int i = 1;i <= 9;i ++)
{
if(!ever[i]) return false;
}
return true;
}
void dfs_c(int x,int a,int c)
{
if(x >= 9) return ;
if(check(a,c)) ans++;
for(int i = 1;i <= 9;i ++)
{
if(!had_use[i])
{
had_use[i] = 1;
dfs_c(x + 1 , a , c*10 + i);
had_use[i] = 0;
}
}
}
void dfs_a(int x,int a) // x 已经使用过的数字, a 当前 a 的值
{
if(a >= n) return ;
if(a) dfs_c(x+1,a,0); // 将该情况下的a 传到 c的dfs 中
for(int i = 1;i <= 9; i++)
{
if(!had_use[i])
{
had_use[i] = 1;
dfs_a(x + 1 , a*10 + i);// 进入下一个dfs
had_use[i] = 0; // 回溯
}
}
}
int main()
{
cin >> n;
dfs_a(0,0);
cout << ans;
return 0;
}