【洛谷 | 入门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
    评论
对于洛谷上的p1036题目,我们可以使用Python来解决。下面是一个可能的解法: ```python def dfs(nums, target, selected_nums, index, k, sum): if k == 0 and sum == target: return 1 if index >= len(nums) or k <= 0 or sum > target: return 0 count = 0 for i in range(index, len(nums)): count += dfs(nums, target, selected_nums + [nums[i]], i + 1, k - 1, sum + nums[i]) return count if __name__ == "__main__": n, k = map(int, input().split()) nums = list(map(int, input().split())) target = int(input()) print(dfs(nums, target, [], 0, k, 0)) ``` 在这个解法中,我们使用了深度优先搜索(DFS)来找到满足要求的数列。通过递归的方式,我们遍历了所有可能的数字组合,并统计满足条件的个数。 首先,我们从给定的n和k分别表示数字个数和需要选取的数字个数。然后,我们输入n个数字,并将它们存储在一个列表nums中。接下来,我们输入目标值target。 在dfs函数中,我们通过迭代index来选择数字,并更新选取的数字个数k和当前总和sum。如果k等于0且sum等于target,我们就找到了一个满足条件的组合,返回1。如果index超了列表长度或者k小于等于0或者sum大于target,说明当前组合不满足要求,返回0。 在循环中,我们不断递归调用dfs函数,将选取的数字添加到selected_nums中,并将index和k更新为下一轮递归所需的值。最终,我们返回所有满足条件的组合个数。 最后,我们在主程序中读入输入,并调用dfs函数,并输结果。 这是一种可能的解法,但不一定是最优解。你可以根据题目要求和测试数据进行调试和优化。希望能对你有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值