阶乘

递归、尾递归和使用Stream延迟计算优化尾递归

ε祈祈猫儿з 提交于 2020-02-13 10:41:58
我们在学数据结构的时候必然会接触栈(Stack),而栈有一个重要的应用是在程序设计语言中实现递归。递归用途十分广泛,比如我们常见的阶乘,如下代码: 1234 public static int (int n) { if (n == 1) return 1; return n * func1(n - 1);} 就可以用递归实现,而且实现相当简洁。如果要计算n的阶乘,那么只需知道n-1的阶乘再乘以n,同理依次类推,直到当我们计算2的阶乘的时候,只需知道1的阶乘,显然这是递归终止条件,再层层向上返回,直至计算出n的阶乘即可。 从上面的分析可以看出,如果我们要进行递归求解某一问题,需要满足以下两个条件: 能将一个问题转变为另一个新问题,而新问题的解法与原问题相同或者类同,并且新问题的数据规模更小,问题简化。 使用递归的情景是当前数据规模较大,直接计算比较困难,那么可以将该问题进行分解,数据规模越来越小,计算也越来越容易,其实这是“分治法”的体现。 存在递归终止条件,或者说递归的边界。 递归的终止条件是必须的,既然当前问题可以分解,那么就必须存在一个“极限”,分解到什么程度?到哪里停止? “分治法”求解递归问题算法有一个一般形式: 1234 void p(参数列表) { if (递归终止条件成立) 直接求解; // 递归终止条件 else p(较小的参数) // 递归步骤}

leetcode172,阶乘后的零

醉酒当歌 提交于 2020-02-10 16:05:15
题目介绍 给定一个整数 n,返回 n! 结果尾数中零的数量。 示例 1: 输入: 3 输出: 0 解释: 3! = 6, 尾数中没有零。 示例 2: 输入: 5 输出: 1 解释: 5! = 120, 尾数中有 1 个零. 思路分析 看到这个题目我脑子里立马就想到递归求阶乘然后mod10,让计数变量++,再取下一位,但是做了之后我发现,很遗憾,溢出了(我早该想到没这么简单)于是乎我看了一下别人的思路,不禁恍然大悟,其实这道题让求出阶乘后面的0的个数并不用把他的阶乘求出来,我们都知道,两个数相乘要想结尾有0,则必须乘出10来(即使乘出20来,他也是两个10)在阶乘里乘出10的方法就是2*5,而一个阶乘里如果将每个乘数都分解为带2或者带5,比如11! = 11 * 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 = 11 * (2 * 5) * 9 * (4 * 2) * 7 * (3 * 2) * (1 * 5) * (2 * 2) * 3 * (1 * 2) * 1,其中我们不难发现2的个数永远是大于5的个数的,所以我们要找有多少个2 * 5就转化为了要找多少个5,换句话说就是有多少个5就有多少个2 * 5,好的,思路理在这我们就不难想出用n/5来找出5的个数,但是如果我们往后继续求得话会发现25/5=5,但是25的阶乘却含有6个5,分别是5 * 5

C++:阶乘之和

倖福魔咒の 提交于 2020-02-07 06:48:34
题目描述 给定一个非负整数n,请你判断n是否可以由一些非负整数的阶乘相加得到。 输入 有若干组数据。每行一个整数n,保证n<1000000。以负数结束输入。 输出 对于每组数据输出一行,若可以则输出‘YES’,否则输出‘NO’。 样例输入 9 -1 样例输出 YES 因为n<10^7,并且0!+1!+2!+3!+……+10!>10 ^7,那么我们可以定义一个a数组专门来装0到10的阶乘。笔者的在线题库中写的是“非负整数”,有些数据也要加上非负整数0!,否则就错了。因此考虑的时候,要从0开始考虑。0!=1。 我用了一个递归程序来完成,是一个bool型的递归函数。对于一个数据ans,加上a[i]后再递归枚举所有小于i的a[i],就可以找出所有的可能。 为了简洁时间复杂度,我首先找出了小于n的a[i],i最大的值,从i开始往小递归。 题目还要注意一点,是用复数结束输入的,避免输出超限要把输入放在while里面。 在找i的过程中,a[i]等于n就直接输出并continue吧。 不多废话,贴代码(Ctrl c+Ctrl v的朋友看这里): # include <bits/stdc++.h> using namespace std ; int p = 1 , i , n ; int a [ 11 ] = { 1 , 1 , 2 , 6 , 24 , 120 , 720 , 5040 ,

洛谷·拉格朗日差值2

谁都会走 提交于 2020-02-06 08:06:46
初见安~这个题目好冷门啊……这里是传送门: 洛谷P5667 拉格朗日差值2 题解 天知道这个题有多恶心,卡了我一个下午…… 乍一看很简单,给你n+1个点值,求一个n次多项式,并求出从m开始的n个点值。 这种情况下就算是用重心差值都不行了,复杂度会达到 。怎么办呢——就像那些数学题一样,我们考虑化简公式。 假设当前要求的这个数是m+x。首先我们肯定可以直接套用拉格朗日差值公式: 至此,首先前面那一部分累乘我们明显可以利用m>n这个条件将其转化为阶乘之间的操作: 预处理出阶乘后,这个操作就没有任何问题了。接下来看后面那一坨,设为g(x)。 是不是有点卷积的感觉了?那我们就往卷积的方向去构造。明显我们不能直接提i和n-i出来,那i和n-i+x呢? 所以至此我们就把卷积构造出来啦~~~为什么可以直接取到n+x呢?其实我们把a数组的 到 都赋值为0就可以了。也就是该怎么算怎么算。 很明显,a数组的取值范围是 ,b数组为 ,所以总上限至少为3n。 有一个小细节就是:因为m的范围1e8,不宜预处理信息,所以可以借助关于m的运算有下限这一点进行形如m-n+i的阶乘和逆元的预处理。本狸还是比较懒啦,所以就没有预处理,虽然耗时比较大,但是不会超时。 上代码—— #include<algorithm> #include<iostream> #include<cstring> #include

求1加到10的阶乘

╄→尐↘猪︶ㄣ 提交于 2020-02-03 05:50:17
求1加到10的阶乘 # include <stdio.h> int main ( ) { int n = 0 ; int m = 1 ; //储存阶乘 int sum = 0 ; //求和 for ( n = 1 ; n <= 3 ; n ++ ) { m = m * n ; sum = sum + m ; } printf ( "%d" , sum ) ; return 0 ; } 来源: CSDN 作者: 贪心的柠檬 链接: https://blog.csdn.net/qq_42627691/article/details/104145714

LeetCodeNo.60第k个

依然范特西╮ 提交于 2020-02-01 09:01:38
参考评论,我的思路和高赞评论基本一样,也是先确定第一个数,然后第二个数 . . 也是采用列表,计算索引,计算阶乘,更新k值,更新列表。但是我的不足很多: 1 、打算采用递归来做,递归函数参数选用(不断更新的list,n - 1 ,变化的k值) 但发现不需要采用递归,应该类似 for 循环递推 2 、求解阶乘;打算写一个阶乘函数,一直调用函数,却发现可以直接一次计算所有 阶乘,放入数组,需要的时候直接拿 3 、确定索引和改变的k值,是通过计算k / 阶乘的余数是否为 0 ,来分类 int curFactorial = factorials [ n - 1 ] ; int index = ( k % curFactorial != 0 ) ? k / curFactorial + 1 : k / curFactorial 然后发现计算k值的时候也要分类,大大麻烦。参考的解答里面很巧妙,先k - 1 , 再计算index和k都很方便,需要继续体会 4 、list的使用不熟练 list . remove ( index ) 这行代码不仅删除了元素,同时拿到了删除的元素, remove方法是有返回值的,返回的就是被删除的元素,不需要事先用get(index) 方法。 5 、在一个 for 循环里同时干两件事:创建list,计算阶乘,我一开始放在两个 for 循环,代码冗余同时耗费不必要时间。

NOIP复习模拟赛day5

我怕爱的太早我们不能终老 提交于 2020-01-30 14:26:40
前言 今天的题目真TM的♂...... 题目 1.小半 ( h alf .pas/c/cpp) 【问题描述】 “释然、慵懒、尽欢, 时间风干后你与我再无关, 没答案,怎么办,看不惯自我欺瞒。 ” 灯火阑珊,释然的少年写下了n个正整数,它们的乘积为p。 月色旖旎,少年忽然想到,如果把 p再乘上一个正整数q能让它们的积为某个数的阶乘,则称这个数的阶乘为完美阶乘,这个数则为完美数,他厌倦了那些纷扰,只想要知道完美数的最小值,希望你能告诉他。 “灯火阑珊, 我的心借了你的光是明是暗。 ” ——《小半》 【输入】 共两行。 第一行一个正整数 n 。 第二行 n 个正整数 a[i],代表少年写下的n 个 数。 【输出】 共一行 一个正整数,代表完美数的最小值。 【输入输出样例】 1 6 3 样例解释:当p=6,q=1时,p*q=3! 【数据范围】 对于 10%的数据,n<=10 对于 30%的数据,n<=1000 对于 100%的数据,n<=100000,a[i]<=100000 官方题解: 10%~30%:各种暴力 100%:题目要求一个最小的m使m!包含p这个因子。 可以把p分解质因数,假设p=∏ai^bi(ai为质数),那么只要m!包含了每个ai^bi,m!就包含p。 所以对于每个ai^bi,分别求出满足条件的最小的m,取最大值即可。 怎么求m? 先看一个简单的问题: 27

多组数阶乘

天涯浪子 提交于 2020-01-30 07:03:15
Description 筒子想求出若干个数每个数的阶乘,请你帮他吧! Input 若干数N(0<=N<=20) Output 每个数的阶乘 Sample Input 1 1 2 3 Sample Output 1 1 2 6 阶乘本来很容易实现,但是多组数的阶乘纠结了一会,其实这就回到了多组输入输出的问题,利用文件结束标志EOF将判断条件设为 scanf("%d",&n)!=EOF 就OK了。 还有一个就是要注意,因为是计算多组数的阶乘,所以在每次计算一个n的阶乘之前,都要把s重新赋为1,切记!!! # include <stdio.h> int main ( ) { int n , i ; long s = 1 ; while ( scanf ( "%d" , & n ) != EOF ) { if ( n <= 1 ) { s = 1 ; printf ( "%ld\n" , s ) ; } else { s = 1 ; //将s重新赋为1 for ( i = 1 ; i <= n ; i ++ ) { s * = i ; } printf ( "%ld\n" , s ) ; } } return 0 ; } 来源: CSDN 作者: ChanCherry min 链接: https://blog.csdn.net/ITmincherry/article/details

扩展 Lucas 定理

蓝咒 提交于 2020-01-27 03:50:52
扩展Lucas定理 原问题 求: \[ C^{n}_{m}\quad(mod\;p) \] 其中, \(n\) , \(m\) 很大,不能够直接求阶乘。 \(p\) 大小可接受但是不保证是质数。 学过 \(Lucas\) 定理后,我们知道其限制是 \(p\) 必须为质数。 我们可以分解问题: 既然去了这个条件,我们可以将 \(p\) 进行质因数分解,模每一个 \(p_i^{k_i}\) ,然后就相当于得到一组同余方程组。 用 \(CRT\) 解出即可。 本人在这里因为 \(CRT\) 学的不太好产生了一个错误思路,导致纠结好久, 总结在此 。 若有人同样误入歧途,希望有些许帮助。(如果没有纠结什么奇怪想法最好先不看 那么现在问题是解: \[ C^{n}_{m}\implies\frac{m!}{(n)!(m-n)!} \quad(mod\;p_i^{k_i}) \] 问题有二: 一, \(m,n\) 都很大,不能直接求出阶乘。 ​ 二, \(n!,(m-n)!\) 内可能有 \(p_i\) 这个因子,无法求出逆元。 很难解决,但是我们发现,阶乘取模一个数后呈现一个以长 \(p_i^{k_i}\) 循环节不断循环的模式,似乎可以只处理一个循环节,再处理余项,两者长度都不超过 \(p_i^{k_i}\) ,可以接受。 另外,从其中我们可以提出所有的 \(p_i\) 使式子变成这样: \

python模块二(递归,反射,正则表达式)

故事扮演 提交于 2020-01-26 23:18:07
一、递归,阶乘 递归之实例: def func(num): """ 1*2*3*4*5... 计算类型形式的阶乘 :param num: 计算阶乘的最大值 :return: 7 * (7 - 1) """ # 如果参数为1,直接返回1 if num == 1: return 1 # 否则返回2 * (2 - 1) return num * func(num - 1) x = func(5) print(x) # ########print########### 120 print(1 * 2 * 3 * 4 * 5) # ########print########### 120 二、反射 反射关键:      反射: 基于字符串的形式去对象(模块)中操作其成员          基于内存操作的     delattr    删除成员     setattr    设置成员     getattr    获取成员     hasattr    检查成员   学习反射之前先了解一下下面的知识 # 定义一个函数名为f1 def f1(): print('F1') # 字符串f1 "f1" # 那么函数名的f1与字符串的f1是否一样 答案是不一样 f1 是 函数名,代表整个函数体 "f1"是 字符串,仅代表字符串本身 现在以一个实例来学习反射 #!/bin/bin/env python #