0
点赞
收藏
分享

微信扫一扫

信息学奥赛一本通 ybt 1173:阶乘和 | OpenJudge NOI 1.6 15 | 洛谷 P1009 [NOIP1998 普及组] 阶乘之和

时光已翩然轻擦 2022-01-20 阅读 42
c++NOIP

【题目链接】

ybt 1173:阶乘和
注:一本通上这题,应该把 n ≤ 50 n\le50 n50当做 n ≤ 100 n\le100 n100来看
OpenJudge NOI 1.6 15:阶乘和
洛谷 P1009 [NOIP1998 普及组] 阶乘之和

【题目考点】

1.高精度

高精乘低精 高精加高精

【解题思路】

使用高精乘低精完成阶乘运算,使用高精加高精完成加和。
该题难点在于分析结果位数,为数字数组设一个合理的数组长度。(比如不知道结果位数,就设了数组长为10000,那你凭什么认为结果一定小于10000位?总得有点根据吧。)
求数字位数公式:假设数字x有n位,那么 n = ⌊ l g x ⌋ + 1 n = \lfloor lgx \rfloor + 1 n=lgx+1
假设n=50,求 1 ! + 2 ! + . . . + 50 ! 1!+2!+...+50! 1!+2!+...+50!的位数,我们可以不断将结果放大
1 ! + 2 ! + . . . + 50 ! ≤ 50 ∗ 50 ! ≤ 50 ∗ 5 0 50 = 5 0 51 1!+2!+...+50! \le 50*50! \le 50*50^{50}=50^{51} 1!+2!+...+50!5050!505050=5051
5 0 51 50^{51} 5051的位数: ⌊ l g 5 0 51 ⌋ + 1 = ⌊ 51 ∗ l g 50 ⌋ + 1 ≤ ⌊ 51 ∗ l g 100 ⌋ + 1 = 103 \lfloor lg50^{51} \rfloor + 1 = \lfloor 51*lg50 \rfloor + 1 \le \lfloor 51*lg100 \rfloor + 1 = 103 lg5051+1=51lg50+151lg100+1=103
将数字数组长度设为105就可以满足要求。
【注】一本通OJ上本题测试数据有误,需要将数字数组长度设为155才能过(我只试到155能过),否则有几个测试点会报“运行错误”。所以可以当这道题中给定的 n ≤ 50 n\le50 n50当做 n ≤ 100 n\le100 n100来看,这样推算出的数据位数就没有问题了。

【题解代码】

解法1:

本解法中,设置的高精度运算为 a*=b和a+=b。直接设可以完成a+b=c,a*b=c, a=b的高精度计算函数,也可以完成本题,具体做法略。

#include<bits/stdc++.h>
using namespace std;
#define N 155//一本通OJ上必须设为155才能过 洛谷、OpenJudge上设到105就能过 
void Multiply(int a[], int b)//高精乘低精 a *= b
{
    int c = 0, i;
    for(i = 1; i <= a[0]; ++i)
    {
        a[i] = a[i]*b + c;
        c = a[i] / 10;
        a[i] %= 10; 
    }
    while(c > 0)
    {
        a[i] = c % 10;
        c /= 10;
        i++;
    }
    while(a[i] == 0 && i > 1)
        i--;
    a[0] = i;
}
void Add(int a[], int b[])//高精加高精 a += b
{
    int c = 0, i;
    for(i = 1; i <= a[0] || i <= b[0]; ++i)
    {
        a[i] += b[i] + c;
        c = a[i] / 10;
        a[i] %= 10;
    }
    if(c > 0)
        a[i] = c;
    while(a[i] == 0 && i > 1)
        i--;
    a[0] = i;
}
void shownum(int a[])
{
    for(int i = a[0]; i >= 1; --i)
        cout << a[i];
}
int main()
{
    int a[N] = {1, 1}, s[N] = {1, 0}, n;//数字a初值为1 加和s初值为0 
    cin >> n;
    for(int i = 1; i <= n; ++i)
    {
        Multiply(a, i);
        Add(s, a);
    }
    shownum(s);
    return 0;
}
举报

相关推荐

0 条评论