题意:给定一个数n(n<=1000000),判断这个数能否表示为若干个不相等的数的阶乘之和。比如9=1!+2!+3!。
思路:方法一:因为n较小,所以先求出<=1000000的阶乘,也就10个左右,然后采用子集和,判断哪些数能够由这些阶乘组成。记录即可。
方法二:一个逆天的性质:因为1!+2!+3!<4!,这情况的成立,所以如果这个数能够表示成为多个数的阶乘,那么我们可以转换为这个数减去他能减掉的最大的阶乘的数是否能被表示。(http://blog.csdn.net/kyou007/article/details/5946534)
#include <stdio.h>
#include <string.h>
#define N 1000000
int dp[N+5],f[30],n;
int getfac(){
int i;
f[0] = 1;
f[1] = 1;
for(i = 2;f[i-1]<=N;i++)
f[i] = f[i-1]*i;
return i;
}
void init(){
int i,j,len;
memset(dp,0,sizeof(dp));
len = getfac();
dp[0] = 1;
for(i = 0;i<len;i++)
for(j = N;j>=0;j--)
if(dp[j] && j+f[i]<=N)
dp[j+f[i]] = 1;
}
int main(){
init();
while(scanf("%d",&n) && n>=0){
if(n && dp[n])
printf("YES\n");
else
printf("NO\n");
}
return 0;
}