1209. 带分数
题目链接
1209. 带分数
\(100\) 可以表示为带分数的形式:\(100=3+\frac{69258}{714}\)
还可以表示为:\(100=82+\frac{3546}{197}\)
注意特征:带分数中,数字 \(1∼9\) 分别出现且只出现一次(不包含 \(0\))。
类似这样的带分数,\(100\) 有 \(11\) 种表示法。
输入格式
一个正整数。
输出格式
输出输入数字用数码 \(1∼9\) 不重复不遗漏地组成带分数表示的全部种数。
数据范围
\(1≤N<10^6\)
输入样例1:
100
输出样例1:
11
输入样例2:
105
输出样例2:
6
解题思路
暴力dfs
先枚举出整数部分,再对剩余分数进行枚举,枚举分母,判断分子是否符合题意,对分子可以进行剪枝:分子末尾不能为 \(0\),位数要大于分母的位数
- 时间复杂度:\(O(9!)\)
代码
// Problem: 带分数
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/1211/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
int res,n,cnt;
bool v[10];
void dfs1(int x,int down,int lst,int used)
{
if(x==n)return ;
int up=down*x;
if(down&&(up%10)&&lst>=(used+1)/2)
{
bool f=true;
int count=0;
bool bv[10];
memcpy(bv,v,sizeof v);
do
{
if(up%10==0||bv[up%10])
{
f=false;
break;
}
bv[up%10]=true;
count++;
up/=10;
}while(up);
res+=f&&(count==lst);
}
for(int i=1;i<=9;i++)
{
if(v[i])continue;
v[i]=true;
dfs1(x,down*10+i,lst-1,used);
v[i]=false;
}
}
void dfs(int x)
{
if(x>=n)return ;
for(int i=1;i<=9;i++)
{
if(v[i])continue;
if(x*10+i<n)
{
v[i]=true;
cnt++;
dfs(x*10+i);
dfs1(n-x*10-i,0,9-cnt,9-cnt);
cnt--;
v[i]=false;
}
else
return ;
}
}
int main()
{
scanf("%d",&n);
dfs(0);
printf("%d",res);
return 0;
}