【洛谷 | 入门3】循环结构 重点题解记录

P1009 阶乘之和

题目描述

用高精度计算出 S = 1! + 2! + 3! + ⋯ + n!(n ≤ 50)

其中“ ! ”表示阶乘,例如:5! = 5 × 4 × 3 × 2 × 1

输入格式

一个正整数 n

输出格式

一个正整数 S,表示计算结果

输入输出样例

输入#1输出#1
39

说明/提示

【数据范围】

对于 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
217

说明/提示

【数据范围】

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
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值