阶乘的加法
- 格式:doc
- 大小:19.00 KB
- 文档页数:1
//阶乘各算法的 C++ 类实现#include <iostream>#include <cstring>#include <iomanip>#include <cmath>using namespace std;class Factorial {static const int MAXN = 5001; // 最大阶乘数,实际用不到这么大int *data[MAXN]; // 存放各个数的阶乘int *nonzero; // 从低位数起第一个非0数字int maxn; // 存放最大已经计算好的n的阶乘int SmallFact(int n); // n <= 12的递归程序void TransToStr(int n, int *s); // 将数n倒序存入数组中void Multply (int* A, int* B, int* C, int totallen); // 执行两个高精度数的乘法public:Factorial();~Factorial();void Calculate(int n); // 调用计算阶乘int FirstNonZero(int n); // 返回阶乘末尾第一个非0数字int CountZeros(int n); // 返回阶乘末尾有多少个0int SecondNum(int n); // 返回阶乘左边的第二个数字bool CanDivide(int m, int n); // 判断数值 m 是否可以整除 n!void Output(int n) const;};int Factorial::SmallFact(int n) {if (n == 1 || n == 0) return 1;return SmallFact(n-1)*n;}void Factorial::TransToStr(int n, int *tmp) {int i = 1;while (n) {tmp[i++] = n%10;n /= 10;}tmp[0] = i-1;}void Factorial::Multply (int* A, int* B, int* C, int totallen){int i, j, len;memset(C, 0, totallen*sizeof(int));for (i = 1; i <= A[0]; i++)for (j = 1; j <= B[0]; j++) {C[i+j-1] += A[i]*B[j]; // 当前i+j-1位对应项 + A[i] * B[j]C[i+j] += C[i+j-1]/10; // 它的后一位 + 它的商(进位)C[i+j-1] %= 10; // 它再取余即可}len = A[0] + B[0];while (len > 1 && C[len] == 0 ) len--; // 获得它的实际长度C[0] = len;}Factorial::Factorial() { // 构造函数,先把<=12的阶乘计算好maxn = 12; data[0] = new int [2];data[0][0] = 1; data[0][1] = 1;int i, j = 1;for (i = 1; i <= 12; i++) {data[i] = new int [12];j = j*i;TransToStr(j, data[i]);}nonzero = new int [10*MAXN];nonzero[0] = 1; nonzero[1] = 1; // nonzero[0]存储已经计算到的n!末尾非0数}Factorial::~Factorial() {for (int i = 0; i <= maxn; i++)delete [] data[i];delete [] nonzero;}void Factorial::Calculate(int n) {if (n > MAXN) return;if (n <= maxn) return; // <= maxn的,已经在计算好的数组中了int i, j, len;int tmp[12];for (i = maxn+1; i <= n; i++) {TransToStr(i, tmp);len = data[i-1][0] + tmp[0] + 1;data[i] = new int [len+1];Multply(data[i-1], tmp, data[i], len+1);}maxn = n;}int Factorial::FirstNonZero(int n) {if (n >= 10*MAXN) {cout << "Super Pig, your input is so large, cannot Calculate. Sorry! ";return -1;}if (n <= nonzero[0]) return nonzero[n]; //已经计算好了,直接返回int res[5][4] = {{0,0,0,0}, {2,6,8,4}, {4,2,6,8}, {6,8,4,2}, {8,4,2,6}};int i, five, t;for (i = nonzero[0]+1; i <= n; i++) {t = i;while (t%10 == 0) t /= 10; // 先去掉 i 末尾的 0,这是不影响的if (t%2 == 0) { // t是偶数直接乘再取模10即可nonzero[i] = (nonzero[i-1]*t)%10;}else { // 否则转换成 res 数组来求five = 0;while (t%5 == 0) {if (five == 3) five = 0;else five++;t /= 5;}nonzero[i] = res[((nonzero[i-1]*t)%10)/2][five];// (nonzero[i-1]*t)%10/2 正好序号为:1, 2, 3, 4 中的一个}}nonzero[0] = n;return nonzero[n];}/* 阶乘末尾有多少个0,实际上只与5的因子数量有关,即求 n/5+n/25+n/625+...... */ int Factorial::CountZeros(int n) {if (n >= 2000000000) {cout << "Super Pig, your input is so large, cannot Calculate. Sorry! ";return -1;}int cnt = 0;while (n) {n /= 5;cnt += n;}return cnt;}/* 输出N!左边第二位的数字:用实数乘,超过100就除以10,最后取个位即可 */int Factorial::SecondNum(int n) {if (n <= 3) return 0;int i;double x = 6;for (i = 4; i <= n; i++) {x *= i;while (x >= 100) x /= 10;}return (int(x))%10;}bool Factorial::CanDivide(int m, int n) {if (m == 0) return false;if (n >= m) return true;int nn, i, j, nums1, nums2;bool ok = true;j = (int)sqrt(1.0*m);for (i = 2; i <= j; i++) {if (m%i == 0) {nums1 = 0; // 除数m的素因子i的数量while (m%i == 0) {nums1++;m /= i;}nums2 = 0; nn = n;while (nn) { // 求 n 含有 i 因子的数量nn /= i;nums2 += nn;}if (nums2 < nums1) { // 少于m中所含i的数量,则m肯定无法整除n! ok = false;break;}j = (int)sqrt(1.0*m); // 调整新的素因子前进范围}}if (!ok || m > n || m == 0) return false;else return true;}void Factorial::Output(int n) const {if (n > MAXN) {cout << "Super Pig, your input is so large, cannot Calculate. Sorry! ";return;}int i, len = 8;cout << setw(4) << n << "! = "; // 格式控制输出for (i = data[n][0]; i >= 1; i--) {cout << data[n][i];if (++len == 58) { // 实际每输出50个字符就换行len = 8;cout << " ";}}if (len != 8) cout << endl;}int main() {int n, m, i;Factorial f;while (cin >> n) {f.Calculate(n);f.Output(n);cout << "该阶乘末尾第一个非0数字是: " << f.FirstNonZero(n) << endl; cout << "该阶乘总共拥有数字0的个数:" << f.CountZeros(n) << endl; cout << "该阶乘的左边的第2位数字是:" << f.SecondNum(n) << endl; cin >> m;if (f.CanDivide(m, n)) cout << m << " 可以整除 " << n << "! ";else cout << m << " 不能整除 " << n << "! ";}return 0;}//第2部分第(5)个算法的单独实现#include<stdio.h>int A[10] = {1,1,2,6,24,120,720,5040,40320,362880};int ans[1024];int sum;void insert(int* a, int x) { // 插入排序,插成有序表int i, j;for (i = 1; i <= a[0]; i++)if (a[i] >= x) break;if (i <= a[0] && a[i] == x) return; // 如果相等,则不用插入if (i > a[0]) {a[++a[0]] = x;}else {for (j = a[0]++; j >= i; j--)ans[j+1] = ans[j];ans[i] = x;}if (a[0] == 1023) printf(" Array Overflow! ");}void search(int n){for (int i = n; i <= 9; i++){sum += A[i]; if (sum > 1) insert(ans, sum);if (i < 9) search(i+1);sum -= A[i];}}int main(){int n,i;ans[0] = 1; ans[1] = 1; //初始化ans数组,ans[0]表示表长search(0);//printf("len = %d ", ans[0]);while(1){scanf("%d",&n);if(n < 0)break;if(n > 409114){ printf("NO ");continue;}for (i = 1; i <= ans[0]; i++)if (ans[i] == n) {printf("YES "); break;}else if (ans[i] > n) {printf("NO "); break;}}return 0;}//阶乘相关算法及程序有关阶乘的算法,不外乎两个方面:一是高精度计算;二是与数论相关。
基础计算公式范文
以下是一些基础计算公式的详细解释:
1.加法公式:
a+b=c
这是最基本的加法公式,表示将a和b两个数相加得到结果c。
2.减法公式:
a-b=c
这是最基本的减法公式,表示将a减去b得到结果c。
3.乘法公式:
a×b=c
这是最基本的乘法公式,表示将a和b两个数相乘得到结果c。
4.除法公式:
a÷b=c
这是最基本的除法公式,表示将a除以b得到结果c。
5.指数公式:
a^b=c
这是指数运算的公式,表示将a的b次方得到结果c。
例如,2^3=8 6.平均数公式:
平均数 = (a1 + a2 + ... + an) / n
平均数表示一组数的平均值,通过将这组数相加并除以数的个数得到。
7.平方根公式:
√(a)=b
平方根表示一个数的平方根,通过求解一个数的平方根得到结果。
例如,√(9)=3
8.百分比公式:
百分比=(部分/总数)×100
百分比表示一个数相对于另一个数的比例,通过将部分与总数相除并
乘以100得到。
9.阶乘公式:
n!=n×(n-1)×(n-2)×...×2×1
阶乘表示一个数乘以比它小的所有正整数的乘积。
例如,
5!=5×4×3×2×1=120。
以上是一些基础计算公式的示例,它们是解决数学问题的基础。
通过
熟练掌握和灵活运用这些公式,我们可以更快地解决各种数学运算和问题。
1.四则运算公式
-加法:a+b=c
-减法:a-b=c
-乘法:a×b=c
-除法:a÷b=c
2.圆的相关公式
-圆的周长:C=2πr(r为半径)
-圆的面积:A=πr²
3.三角形的相关公式
-三角形的周长:C=a+b+c(a、b、c分别为三条边的长度) -三角形的面积:A=1/2×底×高
4.矩形的相关公式
-矩形的周长:C=2a+2b(a、b分别为矩形的两条边的长度) -矩形的面积:A=a×b
5.正方形的相关公式
-正方形的周长:C=4s(s为边长)
-正方形的面积:A=s²(s为边长)
6.平行四边形的相关公式
-平行四边形的周长:C=2a+2b(a、b分别为临边的长度)
-平行四边形的面积:A=底×高
7.梯形的相关公式
-梯形的周长:C=a+b+c+d(a、b、c、d分别为梯形的四条边的长度) -梯形的面积:A=(上底+下底)×高/2
8.圆柱体的相关公式
-圆柱体的体积:V=πr²h(r为底面半径,h为高)
- 圆柱体的表面积:A = 2πr² + 2πrh
9.直角三角形的勾股定理
-直角三角形中,直角边的平方等于两个其他边平方的和
-a²+b²=c²(a、b为直角边的长度,c为斜边的长度)
10.百分数公式
-百分数x原数=百分之几的数
11.阶乘公式
-n!=n×(n-1)×(n-2)×...×2×1(n为正整数)。
排列组合的运算法则排列组合是数学中的一个重要概念,它用于描述一组对象的不同排列或组合方式。
在实际应用中,排列组合常常用于解决问题,例如在概率和统计、组合数学、计算机科学、经济学和工程学等领域。
本文将介绍排列组合的基本概念和运算法则,以及相关的参考内容。
一、基本概念:1. 排列:指从n个不同元素中选取m个元素进行排序。
排列通常用P(n, m)来表示,其中n为总的元素个数,m为选取的元素个数。
排列的计算公式为P(n, m) = n! / (n-m)!2. 组合:指从n个不同元素中选取m个元素,不考虑其排序。
组合通常用C(n, m)来表示,其中n为总的元素个数,m为选取的元素个数。
组合的计算公式为C(n, m) = n! / (m!(n-m)!)3. 阶乘:指从1到某个正整数n的连续整数相乘的结果。
阶乘通常用n!来表示,其中n! = n * (n-1) * ... * 2 * 1。
二、运算法则:排列组合的运算法则主要包括加法法则、乘法法则和递推法则。
1. 加法法则:对于排列和组合来说,加法法则指的是将问题分解为多个独立的情况,并将它们的结果相加。
例如,要从10个不同的球中选取3个球,有两种情况:第一种情况是选取了红球,第二种情况是选取了蓝球。
根据加法法则,这两种情况下的选球数相加即为总的结果:C(10,3) =C(5,3) + C(5,3) = 10.2. 乘法法则:对于排列和组合来说,乘法法则指的是将多个步骤的结果相乘。
例如,从4个不同的元素中选取2个进行排列,有两个步骤:第一步是选取第一个元素,有4种情况;第二步是选取第二个元素,有3种情况。
根据乘法法则,这两个步骤的结果相乘即为总的排列数:P(4,2) = 4 * 3 = 12.3. 递推法则:递推法则是一种利用已知结果推导出未知结果的方法。
例如,计算组合数C(n, m)时,可以利用以下递推关系:C(n, m) = C(n-1, m) + C(n-1, m-1)。
高中阶乘公式总结大全多篇高中阶乘公式总结大全12篇高中阶乘公式总结大全(1)1 元素与集合的关系:,.2 集合的子集个数共有个;真子集有个;非空子集有个;非空的真子集有个.3 二次函数的解析式的三种形式:(1) 一般式;(2) 顶点式;(当已知抛物线的顶点坐标时,设为此式)(3) 零点式;(当已知抛物线与轴的交点坐标为时,设为此式)(4)切线式:。
(当已知抛物线与直线相切且切点的横坐标为时,设为此式)4 真值表:同真且真,同假或假5 常见结论的否定形式;6 四种命题的相互关系(下图):(原命题与逆否命题同真同假;逆命题与否命题同真同假.)原命题互逆逆命题若p则q若q则p互互互为为互否否逆逆否否否命题逆否命题若非p则非q互逆若非q则非p充要条件:(1)、,则P是q的充分条件,反之,q是p的必要条件;(2)、,且q ≠ p,则P是q的充分不必要条件;(3)、p ≠ p ,且,则P是q的必要不充分条件;4、p ≠ p ,且q ≠ p,则P是q的既不充分又不必要条件。
7 函数单调性:增函数:(1)、文字描述是:y随x的增大而增大。
(2)、数学符号表述是:设f(x)在xD上有定义,若对任意的,都有成立,则就叫f(x)在xD上是增函数。
D则就是f(x)的递增区间。
减函数:(1)、文字描述是:y随x的增大而减小。
(2)、数学符号表述是:设f(x)在xD上有定义,若对任意的,都有成立,则就叫f(x)在xD上是减函数。
D则就是f(x)的递减区间。
单调性性质:(1)、增函数+增函数=增函数;(2)、减函数+减函数=减函数;(3)、增函数-减函数=增函数;(4)、减函数-增函数=减函数;注:上述结果中的函数的定义域一般情况下是要变的,是等号左边两个函数定义域的交集。
复合函数的单调性:等价关系:(1)设那么上是增函数;上是减函数.(2)设函数在某个区间内可导,如果,则为增函数;如果,则为减函数.8函数的奇偶性:(注:是奇偶函数的前提条件是:定义域必须关于原点对称)奇函数:定义:在前提条件下,若有,则f(x)就是奇函数。
数学运算在古代的称呼古代数学运算的称呼及其意义古代数学运算在不同的文化和时期有着不同的称呼,这些称呼反映了当时人们对数学运算的重视和认识。
以下将介绍一些古代数学运算的称呼及其意义。
一、加法运算——足加法运算在古代被称为“足”。
这个称呼源于古代人们对于加法运算的理解。
古人认为,加法运算就是将两个数的“足”相加,从而得到它们的和。
这种称呼简洁明了,表达了加法运算的本质。
二、减法运算——损减法运算在古代被称为“损”。
这个称呼也源于古代人们对于减法运算的理解。
古人认为,减法运算就是将一个数“损”去另一个数,从而得到它们的差。
这种称呼形象生动地揭示了减法运算的过程。
三、乘法运算——积乘法运算在古代被称为“积”。
这个称呼反映了古代人们对乘法运算的认识。
古人认为,乘法运算就是将两个数相乘后得到的结果,就像是农田中播种的种子一样,通过“积”累起来,最终得到丰富的收获。
这种称呼寓意着乘法运算的重要性和积累的力量。
四、除法运算——商除法运算在古代被称为“商”。
这个称呼源于古代人们对除法运算的理解。
古人认为,除法运算就是将一个数分成若干个相等的部分,这些部分就像是商品的“商”一样,每个部分的大小就是商的值。
这种称呼形象地表达了除法运算的过程和结果。
五、开方运算——平方根、立方根开方运算在古代并没有一个统一的称呼,而是根据所开方的次数而有不同的名称。
对于二次方根,古代称之为“平方根”,表示对一个数的平方进行开方运算;对于三次方根,古代称之为“立方根”,表示对一个数的立方进行开方运算。
这些称呼清晰地表达了开方运算的次数和运算的目的。
六、乘方运算——幂乘方运算在古代被称为“幂”。
这个称呼反映了乘方运算的本质。
古人认为,乘方运算就是将一个数连续乘以自己若干次,从而得到一个较大的数。
这种称呼简明扼要地表达了乘方运算的特点。
七、阶乘运算——阶阶乘运算在古代被称为“阶”。
这个称呼源于古代人们对阶乘运算的理解。
古人认为,阶乘运算就是将一个数连续乘以小于它的所有正整数,从而得到一个较大的数。
大数的阶乘众所周知,阶乘的定义就是n! = (n-1)!*n,但是有基本的初始条件的,即0! = 1因此1! = 1*0! = 1 * 1 = 1;2! = 2*1! = 2 * 1 = 2;依次类推,但是当n足够大时,整型根本无法装下n的阶乘,如果用C语言来实现的话,根本不可能,那怎么办呢?其实阶乘也无非是乘法和加法罢了,如4!= 24;我们可以用数组来存各位,结舌数组的起始长度是1哈,每当遇到超过长度时,就自加1,不过这里要稍微处理下的,我们可以倒过来存,以便做乘法的,可以这样来存。
4! 4 25! = 5 * 4!,可以用5去乘以4,如果大于10则需向高位进位,下一位的结果就等于下一位乘以5然后加上刚才的进位,当然也要取余数哈,然后继续看有没进位哈,知道遍乘数组每一位哈。
给个能求1000!的例子,用C语言实现的,供大家参考,以便交流学习哈。
#include <iostream>using namespace std;#define N 1000 // 所需求的N的阶乘static int a[N*3]; // 保存阶乘的各位int main(){int i,j; //临时变量int len = 1;int tem,carry;a[1] = 1; //1的阶乘for (i = 2;i<=N;i++) //求阶乘的方法{carry = 0;for (j=1;j<=len;j++){tem = a[j]*i +carry;a[j] = tem%10;carry = tem/10;if (j==len&&carry!=0){len++;}}}for (i = len;i>=1;i--) //输出各位{cout<<a[i];}cout<<endl;return 0;}我们也可以用Python来实现的哈,很简单两句话,就好啦Import mathMath.factorial(1000)就OK了,爽把!不过3.x以上的版本才有此函数哈。
*************************************(1)************************************ ****************假如需要计算n+16的阶乘,n+16接近10000,已经求得n!(共有m个单元),(每个单元用一个long数表示,表示1-100000000)第一种算法(传统算法)计算(n+1)! 需要m次乘法,m次加法(加法速度较快,可以不予考虑,下同),m次求余(求本位),m次除法(求进位),结果为m+1的单元计算(n+2)! 需要m+1次乘法,m+1次求余,m+1次除法, 结果为m+1个单元计算(n+3)! 需要m+1次乘法,m+1次求余,m+1次除法,结果为m+2个单元计算(n+4)! 需要m+2次乘法,m+2次求余,m+2次除法,结果为m+2个单元计算(n+5)! 需要m+2次乘法,m+2次求余,m+2次除法,结果为m+3个单元计算(n+6)! ...计算(n+7)! ...计算(n+8)! ...计算(n+9)! ...计算(n+10)! ...计算(n+11)! ...计算(n+12)! ...计算(n+13)! ...计算(n+14)! 需要m+7次乘法,m+7次求余,m+7次除法,结果为m+7个单元计算(n+15)! 需要m+7次乘法,m+7次求余,m+7次除法,结果为m+8个单元计算(n+16)! 需要m+8次乘法,m+8次求余,m+8次除法,结果为m+8个单元该算法的复杂度:共需:m+(m+8)+(m+1+m+7)*7=16m+64次乘法,16m+64次求余,16m+64次除法第二种算法:1.将n+1 与n+2 相乘,将n+3 与n+4 相乘,将n+5 与n+6...n+15与n+16,得到8个数,仍然叫做n1,n2,n3,n4,n5,n6,n7,n82. n1 与n2相乘,结果叫做p2,结果为2个单元,需要1次乘法。
c语⾔⼤数加法、阶乘和乘法⼀.⼤数加法定义两个⾜够⼤的数字,其数值远超过long的取值范围,设该⼤数的位数有两百位,求其相加所得⼤数加法的核⼼思想详见此链接,内有详细的动画演⽰,这⾥不再赘述直接上代码:#include<string.h>#include<stdio.h>#define N 10//定义当前⼀个⾜够⼤的数字为10位,可任意更改void print_num(int a[],int n){int i=n-1;//从逆序数组的最后⼀项开始查找,进⾏反逆序while(a[i]==0)//由于规定的数组⽐真实计算的数字⼤,所以数组最后⼏位必定存在0的情况--i;//这种情况下⼀定要将0舍去,否则会抬⾼数组的位数for(;i>=0;i--)//找到⾮零的数组,进⾏反逆序输出printf("%d",a[i]);}void plus(int num1[],int num2[],int n){//尤其注意!由于数组是逆序的,所以num[0]是个位,num[1]是⼗位,num[2]是百位for(int i=0,up=0;i<n;i++)//算法参考⼩学加法,这⾥定义⼀个up进位标记{int temp=num1[i]+num2[i]+up;//up最开始设为0,因为在个位⽆法获取进位num1[i]=temp%10;//若产⽣进位⾏为,则选取个位部分赋给num1up=temp/10;//在个位上,若个位相加产⽣进位,则⽤temp/10取整加到下⼀次的⼗位上}print_num(num1, n);}int main(){char buffer1[]="123456";//缓冲数组,将当前数组倒序写⼊num1中char buffer2[]="78951234";//同上,写⼊num2中int num1[N]={0};//将num1,2全部置为0,⽤来将缓冲数组写⼊到num数组当中int num2[N]={0};int n=N;//定义上述两个数组的长度为10for(int i=0,temp=(int)strlen(buffer1)-1;temp>=0;temp--)num1[i++]=buffer1[temp]-'0';//⽤倒序的⽅式将缓冲数组写⼊num中,意味着num的第⼀位是个位,第⼆位是⼗位,三是百位...for(int i=0,temp=(int)strlen(buffer2)-1;temp>=0;temp--)num2[i++]=buffer2[temp]-'0';plus(num1, num2, n);//将两数字相加printf("\n");}⼆.⼤数阶乘⼤数阶乘的中⼼思想参考上述视频和⼀篇博客,博客详情:但是,这⾥需要说明⼀个点:1*2=2,将2存到a[0]中,接下来是⽤a[0]*3;2*3=6,将6储存在a[0]中,接下来是⽤a[0]*4;6*4=24,是两位数,那么24%10==4存到a[0]中,24/10==2存到a[1]中,接下来是⽤a[0]*5;a[1]*5+num(如果前⼀位相乘结果位数是两位数,那么num就等于⼗位上的那个数字;如果是⼀位数,num==0)24*5=120,是三位数,那么120%10==0存到a[0]中,120/10%10==2存到a[1]中,120/100==1存到a[2]中由于上述博客存在某些地⽅没有说清楚的情况,这⾥解释⼀下关于上述博客的Q&A:1.这⾥的num指的是什么?答:这⾥的num指的是前⾯两数值相乘后进位数位多少:例如6*4得24,这⾥的num值的是24/10=2,进位数为2,num=22.下⾯代码为什么要充i=2开始?答:如果这⾥看懂了代码其实理解2不是很难,但是没有看懂是真的难懂:⾸先明确⼀点:5的阶乘是1*2*3*4*5,我定义的value数组的第⼀位为1,⽽我的i是从2起的,这样以来不就直接凑出了1*2了吗?当我的i⾃增到3,我直接在value数组中找出1*2的值,拿他们去和3相乘,也就凑成了1*2*3了3.如何在代码当中表现出进位的思想?答:我们以5!为例,当计算到1*2*3*4的时候,value当中的表现形式是42000000,从左到右依次是个位,⼗位,百位,千位...etc(value表⽰的是24这个数字)我们在关于j的循环当中拿i=5去和value数组求乘积:5先和位于个位的4求积得20:20%10得0,0放⼊个位中;20/10得2,进位为2,up=2。