随笔-80  评论-24  文章-0  trackbacks-0
给定一个非负整数n,判断n是否表示成若干阶乘的和,n = a1! + a2! + a3! + ... + ai!其中a1、a2、...、ai各不相等。
这里限定n为一个比较小的数,如1000000。

因为n比较小,可以先把i!算出来保存下来,当i为10时,10!已经比1000000大了,所以我们只需要搜索n是否能表示成1!~9!中的若干个阶乘之和即可。简单的搜索题,代码如下:

#include <cstdio>                                                                  
                                                                                   
#define MAX 100                                                                    
                                                                                   
int a[MAX];                                                                        
                                                                                   
int init() {                                                                       
  int i = 1;                                                                       
  int res = 1;                                                                     
  while (res < 1000000) {                                                          
    a[i] = res;                                                                    
    i++;                                                                           
    res *=i;                                                                       
  }                                                                                
  return i - 1;                                                                    
}                                                                                  
                                                                                   
int is_factorial_sum(int sum, int index) {                                         
  if  (sum == 0) {                                                                 
    return 1;                                                                      
  } else if (sum < 0 || index < 0) {                                               
    return 0;                                                                   
  }                                                                                
  if (is_factorial_sum(sum - a[index], index - 1)) {                               
    return 1;                                                                      
  }                                                                                
  return is_factorial_sum(sum, index - 1);                                         
}                                                                                  
                                                                                   
int main() {                                                                       
  int len = init();                                                                
  int cases;                                                                       
  scanf("%d", &cases);                                                             
  while (cases--) {                                                                
    int n;                                                                         
    scanf("%d", &n);                                                               
    if (is_factorial_sum(n, len)) {                                                
      printf("Yes\n");                                                             
    } else {                                                                       
      printf("No\n");                                                              
    }                                                                              
  }                                                                                
  return 0;                                                                        
}

因为这里的n不大,所以可以直接暴力搜索,但是如果n非常大了怎么办?
这里提供一个非常棒的思路:
注意到ai! > ai-1! + ai-2! + ... + a1!
这个式子非常容易证明,因为ai-1! + ai-2! + ... + a1! < (i-1)ai-1! < iai-1! = ai!
有了这个式子,我们可以非常容易得利用贪心算法,因为对于任意的n,可以从最大的阶乘开始枚举,一旦aj+1! > n && aj! < n,那么如果n可以表示成阶乘之和的话那么aj!必然是其中一项!
代码如下:

 1 #include <cstdio>                                                               
 2                                                                                 
 3 #define MAX 100                                                                 
 4                                                                                 
 5 int a[MAX];                                                                     
 6                                                                                 
 7 int init() {                                                                    
 8   int i = 1;                                                                    
 9   int res = 1;                                                                  
10   while (res < 1000000) {                                                       
11     a[i] = res;                                                                 
12     i++;                                                                        
13     res *=i;                                                                    
14   }                                                                             
15   return i - 1;                                                                 
16 }                                                                               
17                                                                                 
18 int main() {                                                                    
19   int len = init();                                                             
20   int cases;                                                                    
21   scanf("%d", &cases);                                                          
22   while (cases--) {                                                             
23     int n, i;                                                                   
24     scanf("%d", &n);                                                            
25     for(i = len; i > 0; --i) {                                                  
26       if (n == a[i]) {                                                          
27         n = 0;                                                                  
28         break;                                                                  
29       } else if (n > a[i]) {                                                    
30         n -= a[i];                                                              
31       }                                                                         
32     }                                                                           
33     if (n == 0) {                                                               
34       printf("Yes\n");                                                          
35     } else {                                                                    
36       printf("No\n");                                                           
37     }                                                                           
38   }                                                                             
39   return 0;                                                                     
40 }
posted on 2012-09-17 20:45 myjfm 阅读(1978) 评论(0)  编辑 收藏 引用 所属分类: 算法基础

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理