P1009 阶乘之和
题目描述
用高精度计算出 S = 1! + 2! + 3! + ⋯ + n!(n ≤ 50)
其中“ ! ”表示阶乘,例如:5! = 5 × 4 × 3 × 2 × 1
输入格式
一个正整数 n
输出格式
一个正整数 S,表示计算结果
输入输出样例
输入#1 | 输出#1 |
---|---|
3 | 9 |
说明/提示
【数据范围】
对于 100% 的数据,1 ≤ n ≤ 50
【其他说明】
注,《深入浅出基础篇》中使用本题作为例题,但是其数据范围只有 n ≤ 20,使用书中的代码无法通过本题。
如果希望通过本题,请继续学习第八章高精度的知识
题解
分析
首先看到阶乘第一个想到的肯定是用递归算法,但是由于n的范围过大,所以如果采用递归算法,没有合适的基本数据类型能够完全满足n ≤ 50内的阶乘,所以根据说明/提示,本题的考点在于高精度的整数的存储和运算,并且不能使用递归算法解决(因为保存中间值的代价过大)
思路
分析得出,面对高精度的整数,基本数据类型都无法满足其存储所需要的空间。所以采用数组的方式存储,数组的每一个元素都对应着整数中的每一位数字;关于高精度整数的运算,则自己定义高精度加法和高精度乘法来解决运算问题。需要注意的是,在运算中的进位和留位的方法,通过求10的商和余数来解决
实现
#include<iostream>
using namespace std;
int fac[70];//for(i : 1 to n){fac = fac * i}
int sum[70];//sum = sum + fac
int sz = 70;
//初始化数组为0
void init(int a[])
{
for (int i = 0; i < sz; i++)
{
a[i] = 0;
}
}
//自定义高精加
void aplus(int a[], int b[])
{
for (int i = sz - 1; i >= 0; i--)
{
a[i] += b[i];
}
for (int j = sz - 1; j >= 0; j--)
{
//进位
a[j - 1] += a[j] / 10;
//留位
a[j] = a[j] % 10;
}
}
//自定义高精乘
void mult(int a[], int m)
{
int carry = 0;//进位
for (int i = sz - 1; i >= 0; i--)
{
a[i] = a[i] * m + carry;
carry = a[i] / 10;
a[i] = a[i] % 10;
}
}
//打印数字
void printnum(int a[])
{
int flag = 0;//当前位是否为有效位
for (int j = 0; j < sz; j++)
{
if (a[j] != 0)
{
flag = 1;
}
if (flag)
{
cout<<a[j];
}
}
cout<<endl;
}
int main()
{
int n;
cin>>n;
init(fac);
init(sum);
fac[sz - 1] = 1;//阶乘初始值设为1
for (int i = 1; i <= n; i++)
{
cout<<i<<':';
mult(fac,i);
aplus(sum,fac);
printnum(fac);
}
printnum(sum);
return 0;
}
输入/输出
PS F:\VSC\exercise> cd "f:\VSC\exercise\" ; if ($?) { g++ Untitled-1.cpp -o Untitled-1 } ; if ($?) { .\Untitled-1 }
50
1:1
2:2
3:6
4:24
5:120
6:720
7:5040
8:40320
9:362880
10:3628800
11:39916800
12:479001600
13:6227020800
14:87178291200
15:1307674368000
16:20922789888000
17:355687428096000
18:6402373705728000
19:121645100408832000
20:2432902008176640000
21:51090942171709440000
22:1124000727777607680000
23:25852016738884976640000
24:620448401733239439360000
25:15511210043330985984000000
26:403291461126605635584000000
27:10888869450418352160768000000
28:304888344611713860501504000000
29:8841761993739701954543616000000
30:265252859812191058636308480000000
31:8222838654177922817725562880000000
32:263130836933693530167218012160000000
33:8683317618811886495518194401280000000
34:295232799039604140847618609643520000000
35:10333147966386144929666651337523200000000
36:371993326789901217467999448150835200000000
37:13763753091226345046315979581580902400000000
38:523022617466601111760007224100074291200000000
39:20397882081197443358640281739902897356800000000
40:815915283247897734345611269596115894272000000000
41:33452526613163807108170062053440751665152000000000
42:1405006117752879898543142606244511569936384000000000
43:60415263063373835637355132068513997507264512000000000
44:2658271574788448768043625811014615890319638528000000000
45:119622220865480194561963161495657715064383733760000000000
46:5502622159812088949850305428800254892961651752960000000000
47:258623241511168180642964355153611979969197632389120000000000
48:12413915592536072670862289047373375038521486354677760000000000
49:608281864034267560872252163321295376887552831379210240000000000
50:30414093201713378043612608166064768844377641568960512000000000000
31035053229546199656252032972759319953190362094566672920420940313
P1075 质因数分解
题目描述
已知正整数nn是两个不同的质数的乘积,试求出两者中较大的那个质数
输入格式
一个正整数n
输出格式
一个正整数p,即较大的那个质数
输入输出样例
输入#1 | 输出#1 |
---|---|
21 | 7 |
说明/提示
【数据范围】
n ≤ 2 × 109
【其他说明】
NOIP 2012 普及组 第一题
题解
分析
现在已知n为两个质数乘积,即我们求出两个质数中任意一个即可得到另一个并进行比较,然后输出较大的那个质数。如果先求较大的质因数,需要从n递减到 [ n ] [\sqrt n] [n],当n的数量级比较大且两个质因数相近时,循环次数就很多,所以选择先求较小的质因数,从1递增到 [ n ] [\sqrt n] [n],减少循环次数和计算量
思路
从1到 [ n ] [\sqrt n] [n]循环是否为n的因子,如果是就直接用它除n得到的另一个因数即为所求
实现
#include<iostream>
using namespace std;
int main() {
int n;
cin >> n;
for (int i = 2; i <= n; i++)
{
if (n % i == 0)
{
cout << n / i;
break;
}
}
return 0;
}
输入/输出
PS F:\VSC\exercise> cd "f:\VSC\exercise\" ; if ($?) { g++ Untitled-1.cpp -o Untitled-1 } ; if ($?) { .\Untitled-1 }
21
7