是否阶乘之和(详细思路)

输入一个整数N,判断其是否可以表示成一个正整数阶乘的形式或者几个不同正整数的阶乘之和。
输入 4,-1,0,6,^Z
输出 no, no, no, yes

思路:

设函数f(N)判断N是否可以表示成一个或几个不同整数的阶乘和。

 1. 当N<=0时,f(N)=NO。 
 2. 当N=1时,f(N)=YES。 
 3. 当N=2时,f(N)=YES。
    当N为大于2的奇数时,因为只有1的阶乘是奇数,其他正整数的阶乘都是偶数,所以必然需要分成1的阶乘和其他整数的阶乘之和,所以f(N)=f(N-1)。
    
    当N为大于2的偶数时,假设N最终可分成n1、n2、n3、……、nk(n1、n2、n3、……nk各不相同,且n1<n2<n3<……<nk)的阶乘和
    即N=n1!+n2!+n3!+……+nk!,提取公因子,
      N=n1!*(1 + (n1+1)*(n1+2)*……*n2 + (n1+1)*(n1+2)*……*n3 + …… + (n1+1)*(n1+2)*……*nk)
      
    所以仅需判断N是否可以表示成该公式,
    如果N不能表示成n1的阶乘,则为NO,
    
    接下来判断剩余部分
    (用N1表示)能否表示成
    1 + (n1+1)*(n1+2)*……*n2 + (n1+1)*(n1+2)*……*n3 + …… + (n1+1)*(n1+2)*……*nk,
    如果N1为1则为YES,
    否则N1减去1后,能否表示成
     (n1+1)*(n1+2)*……*n2 + (n1+1)*(n1+2)*……*n3 + …… + (n1+1)*(n1+2)*……*nk,
     首先能否提取公因子 (n1+1)*(n1+2)*……*n2,以此类推……
#include 
using namespace std;
int isFactorialSum(int n) {
  if (n <= 0) {
    return 0;
  }

  if (n == 1 || n == 2) {
    return 1;
  }

  if (n % 2 == 1) {
    return isFactorialSum(n - 1);
  }

  int k = 2;
  while (1) {
    if (n % k != 0) {
      break;
    }

    while (n % k == 0) {
      n /= k;
      k++;
    }

    if (n == 1) {
      return 1;
    }

    if (n < k) {
      break;
    }
    n--;
  }
  return 0;
}
int main()
{
	int n; 
	while(cin>>n)
	{
		if(isFactorialSum(n)==0) cout<<"no"<<endl;
		else cout<<"yes"<<endl;
	}	
	return 0; 
}  

是否阶乘之和(详细思路)_第1张图片

你可能感兴趣的:(NBUOJ)