蓝桥杯——带分数

原题链接:acwing.带分数

题目描述

100 可以表示为带分数的形式: 100 = 3 + 69258 714 100 = 3 + \frac {69258}{714} 100=3+71469258

还可以表示为: 100 = 82 + 3546 197 100 = 82 + \frac {3546}{197} 100=82+1973546

注意特征:带分数中,数字 1 ∼ 9 1∼9 19分别出现且只出现一次(不包含 0 0 0)。

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

输入格式

一个正整数。

输出格式

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

数据范围

1 ≤ N < 1 0 6 1≤N<10^6 1N<106

输入样例1:
100
输出样例1:
11
输入样例2:
105
输出样例2:
6

dfs暴力搜索

直接枚举每一种排列,然后双重循环枚举分界点,将排列分为三部分,求出结果

可以看出,如果第一个数已经大于给定的值,即可及时break掉减少一层循环

时间复杂度

O ( n ! × n ) O(n!×n) O(n!×n)

C++ 代码

#include 
using namespace std;

int n;
const int N = 10;
int a[N];
bool st[N];
int res = 0;

int cal(int l,int r) {
    int ans = 0;
    for(int i = l;i <= r;i ++) ans = ans * 10 + a[i];
    return ans;
}

void dfs(int u) {

    if(u > 9) {

        for(int i = 1;i < 9;i ++) {
            int a = cal(0,i);
            if(a >= n) break;
            for(int j = i + 1;j <= 9;j ++) {

                int b = cal(i + 1,j);
                int c = cal(j + 1,9);
                if(a * c + b == n * c) res ++;
            }
        }

    }

    for(int i = 1;i <= 9;i ++) {
        if(!st[i]) {
            st[i] = true;
            a[u] = i;
            dfs(u + 1);
            st[i] = false;
        }
    }

}

int main()
{
    cin >> n;
    dfs(1);
    cout << res << endl;
    return 0;
}

优化

只需要枚举 a a a c c c,根据 b = c × n − a × c b = c × n - a × c b=c×na×c求出b即可,然后判断b的每一位是否都有用到

那么我们可以嵌套递归,对于 a a a的每一个分支,都递归求出 c c c

C++ 代码

#include 
#include 
#include 

using namespace std;

const int N = 20;
bool st[N], backup[N];
int n;
int ans;

bool check(int a,int c) {

    int b = n * c - a * c;
    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) {

    if(u > 9) return;

    if(check(a,c)) ans ++;

    for(int i = 1;i <= 9;i ++) {
        if(!st[i]) {
            st[i] = true;
            dfs_c(u + 1,a,c * 10 + i);
            st[i] = false;
        }
    }

}

void dfs_a(int u,int a) {

    if(a > n) return;
    if(a) dfs_c(u,a,0);

    for(int i = 1;i <= 9;i ++) {
        if(!st[i]) {
            st[i] = true;
            dfs_a(u + 1,a * 10 + i);
            st[i] = false;
        }
    }

}

int main()
{
    cin >> n;

    dfs_a(0,0);
    cout << ans << endl;
    return 0;
}

你可能感兴趣的:(蓝桥杯,算法,dfs)