帶分數–第四屆藍橋杯省賽C++B/C組

第四屆藍橋杯省賽C++B/C組—-帶分數

思路:

1.先枚舉全排列
2.枚舉位數
3.判斷是否滿足要求
這道題也就是n=a+b/c,求出符合要求的abc的方案數。進行優化時,可以對等式進行改寫,改寫成:b=cn-ca。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 30;
int target,ans = 0;
bool had_use[N],ever[N];

bool check(int a, int c)
{
    int b = c*target - c*a; //寫出式子,算出b
    if (!a || !b || !c) return false;
    memcpy(ever, had_use, sizeof had_use); //拷貝had_use數組給ever,這樣能不改變原來的數組
    while (b)
    {
        int t = b % 10;
        if (!t || ever[t]) return false;
        ever[t] = true;
        b /= 10;
    }
    for (int i = 1; i <= 9; i++)//判斷1-9每個數字有沒有都被用到
        if (!ever[i])   return false;
    return true;
}

void dfs_c(int x, int a, int c)//x表示用了多少個數字,a表示枚舉的a的大小,c表示c的大小
{
    if (x >= 10)    return;//如果1-9全部都已經被枚舉了,則退出
    if (check(a,c)) ans++; //檢驗a和c是否滿足要求,滿足則方案書+1
    for (int i = 1; i <= 9; i++)
    {
        if (!had_use[i])
        {
            had_use[i] = true;
            dfs_c(x+1, a, c*10+i);
            had_use[i] = false;
        }
    }
}

void dfs_a(int u, int a)//u表示枚舉到第幾個位置,也就是用了多少個數字,t表示當前的a是多少
{
    if (a >= target) return;
    if (a) dfs_c(u, a, 0); //如果a滿足要求,則對c進行枚舉
    
    for (int i = 1; i <= 9; i++)
    {
        if (!had_use[i])
        {
            had_use[i] = true;
            dfs_a(u+1, a * 10 + i);//將i加在a的各位
            had_use[i] = false; //回溯,恢復現場
        }
    }
    
}
int main()
{
    scanf("%d", &target);
    dfs_a(0,0); //先枚舉a
    printf("%d", ans);
    return 0;
}