http://ac.jobdu.com/problem.php?pid=1038
这道题首先想到用组合数,如果要列出完整的组合内容应考虑到用所有组合, 所有排列的模板。如果只是要组合的和(或者积)就相当于二叉搜索,中途还可以剪枝。
code1:
#include <stdio.h>
static int f[11];
static int n;
void make_f(){
f[0] = 1;
for (int i = 1; i < 11 ; ++i) {
f[i] = i * f[i-1];
}
}
bool dfs(int x, int l){
if(x==n) return true;
if(l>10) return false;
if(x>n) return false;
bool b0 = dfs(x,l+1);
if(b0) return true;
x += f[l];
bool b1 = dfs(x,l+1);
return b1;
}
int main(){
make_f();
while(scanf("%d",&n) !=EOF){
if(n==0) printf("NO\n");
else printf("%s\n",dfs(0,0)?"YES":"NO");
}
}
后来看题解发现,其实这是一道可以用贪心算法求解的题。因为f[i] > sum(f[0],,,,f[i-1])。 如果n是sum of factorials,且n>=f[i], 那么n中一定包含f[i],否则后面的所有f[0]...f[i-1]的和加起来都小于n。
code2:
#include <stdio.h>
static int f[11];
void make_f(){
f[0] = 1;
for (int i = 1; i < 11; ++i) {
f[i] = i * f[i-1];
}
}
int main(){
make_f();
int n;
while(scanf("%d",&n)!=EOF){
if(n==0){
printf("NO\n");
continue;
}
for (int i = 10; i >=0 ; --i) {
if (n>=f[i]) {
n -= f[i];
}
}
printf("%s\n",n==0?"YES":"NO");
}
}