帶分數(dfs)

鏈接https://www.acwing.com/problem/content/1211/


題意

100 可以表示爲帶分數的形式:100 = 3 + 69258 / 714。

還可以表示爲:100 = 82 + 3546 / 197。

注意特徵:帶分數中,數字1~9分別出現且只出現一次(不包含0)。

類似這樣的帶分數,100 有 11 種表示法。

輸入

從標準輸入讀入一個正整數N (N<1000*1000)

輸出

程序輸出該數字用數碼1~9不重複不遺漏地組成帶分數表示的全部種數。

樣例輸入1

100

樣例輸出1

11


思路:

先枚舉a的排列,在a的搜索樹的葉子上 再枚舉c的排列,在c的搜索樹的葉子上 再check b是否滿足條件。


代碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=10;
int n,ans;
bool vis[N],backup[N];

bool check(int a,int c){
    ll b=n*(ll)c-a*c;
    if(!a||!b||!c) return false;//不能爲0
    memcpy(backup,vis,sizeof vis);
    while(b){
        int x=b%10;
        b/=10;
        if(!x||backup[x]) return false;//b的該數位爲0或已出現在ac中
        backup[x]=true;
    }
    for(int i=1;i<=9;++i) if(!backup[i]) return false;//都出現過
    return true;
}

void dfs_c(int a,int c){//排列
    if(check(a,c)) ++ans;
    for(int i=1;i<=9;++i){
        if(!vis[i]) {
            vis[i]=true;
            dfs_c(a,c*10+i);
            vis[i]=false;
        }
    }
}

void dfs_a(int a){//排列

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

    for(int i=1;i<=9;++i){
        if(!vis[i]){
            vis[i]=1;
            dfs_a(a*10+i);
            vis[i]=0;
        }
    }
    
}

int main(){
    scanf("%d",&n);
    dfs_a(0);
    printf("%d\n",ans);
    return 0;
}

注意:
1.check裏面c最多是7位數(a 1 位,b 1 位),即c<107,而n<106,因此n * c可能爆int。n*c爆int變負數,b就是負數,b取模得到的x也是負數,backup[x]就會越界。所以把c和b轉成long long。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章