AcWing 1209.带分数


链接:
题目:
100 可以表示为带分数的形式:
还可以表示为:
注意特征:带分数中,数字 1~9 分别出现且只出现一次(不包含 0)。

类似这样的带分数,100 有 11 种表示法。

输入格式
一个正整数。

输出格式
输出输入数字用数码 1~9 不重复不遗漏地组成带分数表示的全部种数。

数据范围
1≤N<106
输入样例1:
100
输出样例1:
11
输入样例2:
105
输出样例2:
6
思路:
给定一个数N,问有多少组a,b,c满足,且a,b,c三个数不重不漏地涵盖1?9这9个数字,输出总组数
暴力枚举出9个数的全排列,然后用一个长度为9的数组保存全排列的结果
从全排列的结果中用两重循环暴力分解出三段,每段代表一个数
验证枚举出来的三个数是否满足题干条件,若满足则计数
题解:

#include 
using namespace std;

const int N=20;   //需要提前预设的变量:保存答案的数组,used数组
int ways[N];  //保存全排列
bool used[N]; //判断是否可用
int n,ans;   //n为输入,ans为答案个数 

int f(int a,int b)  //将分好的一段数字转换成int 
{
	int sum=0;
	for(int i=a;i<=b;i++)
		sum=sum*10+ways[i];
	return sum;
}

void dfs(int u)
{
	if(u>9) //全排列已完成
	{
		if(f(1,i)>n) break;    //剪枝,当a大于n时,一定无解,直接跳出
		for(int i=1;i<=7;i++)   //暴力枚举,两重循环把九位数字分成三段
		{
			for(int j=i+1;j<=8;j++)
			{
                                if(j-i<9-i) continue; //剪枝,当b的位数小于c的位数时,分数小于1,一定不为整数,跳出
				int a=f(1,i);
				int b=f(i+1,j);
				int c=f(j+1,9);
				if(b==n*c-a*c) ans++; 
			}
		}
		return;
	}
	for(int i=1;i<=9;i++)
	{
		if(!used[i]) //如果该数字没有被用过 
		{
			used[i]=true; 
			ways[u]=i;
			dfs(u+1);
			used[i]=false;  //恢复现场
			ways[u]=0;
		}
	}
}

int main()
{
	cin>>n;
	dfs(1);
	cout<