将一个数由几个数的阶乘和表示

问题描述:比如145=1!+4!+5!这样,1400就没有合适的阶乘数的和相加表示。

思考:简单的回溯即可,取该数或者不取该数,不可重复。我事先先存储了前50个数的阶乘。

#include <iostream>

using namespace std;
int jiecheng(int num)
{
if (num == 0)
return 0;
int sum = 1;
for (int i = 1; i <= num; i++)
sum *= i;
return sum;
}
int fanwei=50;
int num;
int cord[50];
int a[50];
void huisu(int sum,int index)
{
if (index == 10)
return;
if (sum == num)
{
for (int i = 0; i<30; i++)
{
if (cord[i] >= 1)
{
for (int j = 1; j <= cord[i];j++)
cout << i << "!+";
}

}
cout << "=" << num << endl;
return ;
}
if (sum > num)
{
return;
}
cord[index] +=1;   //取该数,该坐标位置加1
huisu(sum + a[index], index + 1);       //相加,回溯,判断下一个位置
cord[index] -=1;    //不取该数
huisu(sum, index + 1);     //直接进入判断下一个位置

}
int main(void)
{
cin >> num;
for (int i = 0; i < fanwei; i++)  //存储前50的阶乘
{
a[i] = jiecheng(i);
}
huisu(0, 1);
return 0;

}



///

简单的回溯即可,不需要什么嵌套啥的,最近发现回溯真的好好用啊~哈哈

### 回答1: 可以,可以使用贪心算法,从大到小枚举阶乘,每次尽可能地减去一个阶乘,直到n等于或者无法再减去一个阶乘为止。如果最终n等于,则可以表示成正整阶乘的形式;如果最终n不等于,则不能表示成正整阶乘的形式。 ### 回答2: 阶乘学中的一个概念,表示一个正整及其前面所有正整的积。例如,3的阶乘(记作3!)等于1×2×3=6。因此,正整阶乘的形式,如1!、2!、3!、4!等,都可以表示一个正整的形式。 若输入的整n可以表示一个正整阶乘的形式,那么就直接判断它是否等于某一个正整阶乘。若n可以表示成k!的形式,那么k 就是这个n对应的正整。 如果输入的整n不能表示一个正整阶乘的形式,那么就考虑它是否可以表示几个不同正整阶乘之和。 要判断n能否表示几个不同正整阶乘之和,可以用一个组ans记录所有阶乘的结果,从小到大枚举每个阶乘ans[i],同时计算n-ans[i]得到差值,如果差值可以表示几个不同正整阶乘之和,就说明n可以表示几个不同正整阶乘之和,否则继续枚举下一个阶乘即可。 具体实现代码如下: //输入一个n,判断其是否可以表示一个正整阶乘的形式或者几个不同正整阶乘之和 #include<cstdio> #include<cmath> #include<algorithm> using namespace std; int ans[15]; //阶乘组 bool dfs(int n, int k, int sum) //判断n能否表示成k个不同正整阶乘之和 { //n剩余的小于最小的阶乘ans[1]或者已经找到了k个不同的阶乘 if (n < ans[1] || k == 0) return false; if (sum == n) //找到了一组解 return true; for (int i = 1;i <= 13;i++) { if (ans[i] <= n) //当前阶乘ans[i]小于等于n { if (i > 1 && ans[i] == ans[i - 1]) //去重操作,如果与前一个阶乘相同,跳过 continue; if (sum + ans[i] > n) //如果加上ans[i]后,sum大于n,结束枚举 break; if (dfs(n, k - 1, sum + ans[i])) //递归搜索 return true; //找到了一组解 } } return false; //n不能表示为k个不同正整阶乘之和 } int main() { ans[0] = 1; //预处理0!=1 for (int i = 1;i <= 13;i++) ans[i] = ans[i - 1] * i; //预处理1!到13!,13!已经超出了int范围 int n; scanf("%d", &n); for (int i = 1;i <= 13;i++) if (ans[i] == n) //n可以表示为某个正整阶乘 { printf("%d! = %d\n", i, n); return 0; } for (int i = 1;i <= 13;i++) //n不能表示一个正整阶乘,尝试表示几个不同正整阶乘之和 if (dfs(n, i, 0)) //从1个不同阶乘开始尝试 { printf("%d", n); for (int k = 1;k <= i;k++) //输出所有表示方法 { for (int j = 13;j >= 0;j--) if (ans[j] <= n && dfs(n - ans[j], k - 1, sum + ans[j])) //寻找n-ans[j]是否能表示成k-1个不同正整阶乘之和 { printf(" = %d!", j); sum += ans[j]; //累积减去所有已经找到的阶乘之和ans[j] break; } } printf("\n"); return 0; } printf("%d cannot be expressed as the sum of distinct factorials.\n", n); //n无法表示一个正整阶乘的形式或者几个不同正整阶乘之和 return 0; } ### 回答3: 要判断一个n是否可以表示一个正整阶乘几个不同正整阶乘之和,我们可以考虑使用学归纳法来证明这个问题。 首先,我们知道任何正整n都可以表示为唯一的一组素的乘积,即n=p1^a1 * p2^a2 * … * pk^ak,其中pi为素,ai为正整。根据质因分解定理,我们可以将n唯一分解为素的乘积,那么我们只需要证明当n为素或n为4的倍时,n可以表示一个正整阶乘几个不同正整阶乘之和。 当n为素时,显然n可以表示成n=n!,即n是一个正整阶乘形式。 当n为4的倍时,我们可以将n分解为n=4k (k为正整),那么可以将4拆分为2+2,即n=2!+2!+…+2! (总共有k个2!),因为阶乘的乘法具有可交换性和可结合性,所以2!+2!+…+2!可以简写为k×2!,即n=k×2!,即n可以表示几个不同正整阶乘之和。 接下来,我们证明当n为4的倍以外的偶时,n不可以表示一个正整阶乘形式或几个不同正整阶乘之和。 假设存在一个正整m,使得n=m!或者n可以表示几个不同正整阶乘之和,那么n一定可以表示成n=k1!+k2!+…+km!的形式,其中ki为正整且ki≤n。显然,由于k1≥2,所以k1!中一定有因子2和3,同理可知k2!,k3!,…,km!中也一定有因子2和3,因此k1!+k2!+…+km!中至少有2个因子2和1个因子3。但是,由于n为偶但不是4的倍,所以n至少有4个因子2和1个因子3,因此无法表示成k1!+k2!+…+km!的形式,矛盾。因此,当n为偶且不为4的倍时,n不可以表示一个正整阶乘形式或几个不同正整阶乘之和。 综上所述,当n为素或n为4的倍时,n可以表示一个正整阶乘几个不同正整阶乘之和;当n为偶且不为4的倍时,n不可以表示一个正整阶乘形式或几个不同正整阶乘之和。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值