其实可以用搜索做。
3628800=10*fact(9) 就是这个dfs数的上限。
总体思想:搜索+剪枝,先搜出所有各位阶乘和的位数和本身位数相同的数,然后再仔细判断。
我觉得练习的时候就尽量不要用直接打表法做了吧。。
#include"stdio.h"
#include"stdlib.h"
#include"time.h"
#include"math.h"
#include"iostream"
#include"string.h"
#include"algorithm"
#include"vector"
#include"string"
#include"queue"
#include"map"
#define nmax 1000000
#define inf 0x7ffffff
#define eps 1e-8
#define PI 3.1415926535
#define PRIME 9999991
#define LL long long
///---rand---///
//double random(){return (double)(rand()%RAND_MAX )/RAND_MAX ;}
//int random(int a,int b){return (double)a+random()*(b-a+1);}
///----------///
inline int maxy(int a,int b){return a>b?a:b;}
inline int miny(int a,int b){return a<b?a:b;}
inline long long maxy(long long a,long long b){return a>b?a:b;}
inline long long miny(long long a,long long b){return a<b?a:b;}
using namespace std;
map<long long ,int >mp;
//LL max_int =2147483647;
LL max_int=10000000000000ll;
LL fact[20]={1,1,2,6,24,120,720,5040,40320,362880};
LL dig[20]={0ll,1ll,10ll,100ll,1000ll,10000ll,100000ll,1000000ll,10000000ll,100000000ll,1000000000ll,10000000000ll,
100000000000ll/*12*/,1000000000000ll/*13*/,10000000000000ll/*14*/};
bool is_dfs(LL v){
LL rem=v;
LL ans=0;
while(v>0){
ans+=(LL)fact[v%10];
if(ans>rem)return false;
v/=10;
}
if(ans==rem)return true;
return false;
}
int stk[20];
int cnt;
LL ans[nmax];
void dfs_tranc(int k,LL cursum,int len){
if(k==len){
if(cursum>=dig[len]&&cursum<dig[len+1]&&mp[cursum]==0){//位数是否符合要求
//is a len number.
mp[cursum]++;
if(is_dfs(cursum))
ans[cnt++]=cursum;
}
return ;}
if(cursum+(LL)len-k>=dig[len+1]||(LL)cursum+(LL)(len-k)*fact[9]<dig[len])return ;//剪枝
int i;
for(i=0;i<=9;i++){
//if(k==0&&i==0)continue;
dfs_tranc(k+1,(LL)cursum+fact[i],len);
}
}
int main(){
int i;
cnt=0;
mp.clear();
//long st=clock();
for(i=1;i<=7;i++){
dfs_tranc(0,0,i);
}
for(i=0;i<cnt;i++){
printf("%I64d\n",ans[i]);
}
//printf("Time:%ld\n",clock()-st);
return 0;}