hdu1042 N!
来源:互联网 发布:淘宝代理需要多少钱 编辑:程序博客网 时间:2024/05/16 11:21
题目链接
N!这个题目在算法竞赛入门经典 出现过,过程相当于模拟手算的过程(我的大数乘法也是这样的)。假使我们的现在知道(n-1)! ,那么n!=(n-1)!*n.这个也是显而易见的。
但是n!的结果十分的大,10000!差不多需要45000位数字。所以我们不能简单的使用一个基础类型去进行存储,所以我们想到了另一个东西--------数组,对,没错就是数组,我们可以模拟我们手算的方式来进行计算。
假设我们要求解7!,已知6!,手算过程如下
6!=720.
7 2 0
* 7
--------------------------------
0
1 4
4 9
------------------------------------
5 0 4 0
这个过程相当简单,我们也就是拿7和6!的每一位相乘,然后按照位置加下来就可以了。当然写程序一般我们不会那么做,我们先将乘数与被乘数的第i位相乘得到的结果和上一次的进位结果加起来与10取模(既是求得当前位),放在存储结果的数组的第i位中,记录这次运算的进位(结果除以10就是进位结果),这样循环即可。
result[0]=1;//result是存储结果的数组 //我们存放的顺序是逆序的,以便于我们进位,例如6!=720,你们result存放的是 result[0]=0,result[1]=2,result[2]=7; for(int i=2;i<=n;i++) { int t=0;//进位结果,初始化进位为0 for(int j=0;j<MAXN;j++) { int temp=result[j]*i+t;//被乘数的第i位与乘数相乘加上进位的结果 result[j]=temp%10;//实际上存储的第i位的大小 t=temp/10000;//取得这次运算的进位结果 } }//输出的时候逆序输出即可,记得处理前导零
这样做是没有问题的。但是面对hdu1042需要求10000!这么搞?我一开始使用上面的方法做,果断的TLE(超时),看了别人的一些资料后发现,还可以对上面的代码进行改进。我们可以观察,我们的result数组只存一位,那如果我们的result存的不是一位而是几位是不是会使我们的计算次数变少?怎么做?其实也就是简简单单改一下代码中mod的数和除的数。
result[0]=1; for(int i=2;i<=n;i++) { int t=0; int k=0; for(int j=0;j<MAXN;j++) { int temp=result[j]*i+t; result[j]=temp%10000;//改了这儿 t=temp/10000;//改了这儿 } }
我们这样做为什么是正确的?其实我们也就是把一个数分成了几块来运算而已 ,第一段代码我们使用一块一位,现在我们是一块4位进行计算,进位也是一样。其实是进制的转换,我们从10进制的计算到了万进制的转换。
Q:上面提到的是4位一块,那能不能在提高欸例如6位7位?
A:可以的,分几块基于基础的数据类型,假设你使用int定义一个块,那么必须保证两个块的最大值相乘能够被一个int装起来,不会出现溢出。所以int可以装5位,如果6位和6位会超,可以选用64位整形存储。位数可达9位。
注意:注意多位存储的时候注意0的输出
贴下我的代码:
#include <iostream>#include <stdio.h>#include <cstring>using namespace std;const int MAXN=20000;int result[MAXN];void fac(int n){ memset(result,0,sizeof(result)); result[0]=1; for(int i=2;i<=n;i++) { int t=0; int k=0; for(int j=0;j<MAXN;j++) { int temp=result[j]*i+t; result[j]=temp%10000; t=temp/10000; } } int i=MAXN-1; for(;!result[i];i--); cout<<result[i]; for(i-=1;i>=0;i--) { if(result[i]<10){ cout<<"000"; } else if(result[i]<100){ cout<<"00"; } else if(result[i]<1000){ cout<<"0"; } cout<<result[i]; } cout<<endl;}int main(){ int n; while(cin>>n) { fac(n); } return 0;}
已经ac。
如果我的这篇文中出现什么问题,欢迎批评指正。
- HDU1042 N!
- hdu1042 N!
- N! hdu1042
- hdu1042 N!
- HDU1042--N!
- hdu1042 N!
- HDU1042 N!
- N! HDU1042
- HDU1042---N!
- hdu1042 N!
- HDU1042 N!
- hdu1042 N!
- HDU1042 n!
- hdu1042 - N!
- HDU1042 N!
- HDU1042 N!
- HDU1042(N!)
- HDU1042 N! 万进制
- Android Audio系统分析1(获得最小buffer部分)
- Python笔记-函数(20160319)
- 内存分配
- JavaScript 中的 String.match() 方法
- java中位运算的一点研究
- hdu1042 N!
- 数据挖掘-MATLAB下svm小例子
- 大小端及网络字节序
- 深入理解Java虚拟机笔记---class类文件结构概述
- MotionEvent常量篇
- 关于IList、IQueryable、IEnumerable与Func、Expression的关系2-详解
- Redis快速入门
- wdk驱动开发的特点
- 图片编辑canvas