1209. 带分数 题解

跳转链接

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;
}
95. 费解的开关 题解
1969. 品种邻近 题解
Valaxy v1.0.0-rc.3 驱动|主题-Yunv1.0.0-rc.3