鏈接: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。