洛谷刷题_P1009 [NOIP1998 普及组] 阶乘之和
题目
P1009 [NOIP1998 普及组] 阶乘之和
题目链接
https://www.luogu.com.cn/problem/P1009
知识点
求阶乘正常做法:
#include <stdio.h> long long jiecheng(long long n) { long long a=1; for(int i=1;i<=n;i++){ a*=i; } return a; } int main () { int n; long long sum=0; scanf("%d",&n); for(int i=1;i<=n;i++) { sum+=jiecheng(i); } printf("%lld",sum); return 0; }
本来应该是这样做就可以了,由于n的最大值是50,所以直接这么做会超出long long类型的范围,所以这道题需要用高精度的做法来做。
这里先补充一些C++的知识:结构体中的构造函数(类似于java中的构造方法)
结构体中的构造函数就是为了方便初始化变量用的,因为在结构体中变量无法直接初始化,需要写一个方法来对变量进行初始化,如果我们写的是一个普通方法,每当我们需要初始化变量的时候,就需要去调用这个方法一次,这样较为麻烦。所以我们就可以写一个构造函数,这个构造函数不需要调用(用户也无法调用),它会在创建对象(也就是结构体变量)时,自动调用。
例:
#include <stdio.h> #include<string> using namespace std; struct student{ string name; int age; student() {//通过构造函数来进行初始化 name="jinx"; age=10; } }; int main () { student stu; printf("%s\n",stu.name.c_str());//printf无法直接输出string类型,需要c_str()函数转换一下 printf("%d",stu.age); return 0; }
输出就是jinx,10。
再学一下高精度的算法
在高精度算法中,大数是用一个一维数组来进行存储的,并且数组的低位用来存放数的低位,譬如一个大数为123456,此时a[0]存储的是6,a[1]存储的5,a[2]存储的是4 ... a[5]=1。
高精度的结构:
struct bignum{ int d[1001]; int len; bignum{ memset(d,0,sizeof(d)); len=0; } }
高精度的存储:
bignum saven(char ds[]){//这个ds字符数组中存放的就是一个大数 bignum n; n.len=strlen(ds); for(int i=0;i<n.len;i++) { n.d[i]=ds[n.len-1-i]-'0'; } return n; }
高精度的比较:
//a>b 返回1,a<b 返回-1,a=b 返回0 int compare(bignum a,bignum b) { if(a.len>b.len) return 1; else if(a.len<b.len) return -1; else { for(int i=a.len-1;i>=0;i--) {//从最高位往最低位开始比较 if(a.d[i]>b.d[i]) return 1; else if(a.d[i]<b.d[i]) return -1; } } return 0; }
高精度加法:
例如:123+678=801
这个加法的思想就是:
1.先算8+3,8+3=11,取个位1为结果,并产生高位的进位1;
2.再算2+7,加上来自的进位的1,此时取个位的0为结果,再产生一个进位1;
3.最后计算1+6,再加上来自进位的1,此时没有进位,结果就为8。
最终就是801。
code:
bignum add(bignum a,bignum b) { bignum c; int jinwei=0; for(int i=0;i<a.len || i<b.len;i++) { int temp=a.d[i]+b.d[i]+jinwei; c.d[c.len++]=temp%10;//这里的c的len初始为0,a和b的len都已经计算过 jinwei=temp/10; } if(jinwei!=0) { c.d[c.len++]=jinwei; } return c; }
高精度减法:
例:321-189=132
1-9,不够减,向高位借1,高位-1,原数+10,变成11,11-9=2
2-8,不够减,要先减去被低位借的1,再向高位借1,高位-1,原数+10,2-1+10-8=3
3-1,先减去被低位借的1位,3-1-1=1
bignum sub(bignum a,bignum b){ bignum c; for(int i=0;i<a.len || b.len;i++) { if(a.d[i]<b.d[i]) { a.d[i+1]--; a.d[i]+=10; } c.d[len++]=a.d[i]-b.d[i]; while(c.len>1 && c.d[len-1]==0) { c.len--; } } return c; }
高精度乘法(高精度×低精度):
假设a是高精度的数
bignum mul(bignum a,int b) { bignum c; int jinwei=0; for(int i=0;i<a.len;i++) { int temp=a.d[i]*b; c.d[c.len++]=temp%10+jinwei; jinwei=temp/10; } while(jinwei!=0) { c.d[c.len++]=jinwei; jinwei/=10; } return c; }
高精度除法(高精度÷低精度):
这里要注意的是除法是从被除数的最高位开始除的。
bignum div(bignum a,int b) { bignum c; int yushu=0; c.len=a.len; for(int i=a.len-1;i>=0;i--) { int temp=a.d[i]*10+yushu; c.d[i]=temp/b; yushu=temp%b; } while(c.len>0 && c.d[len--]==0) { c.len--; } c.d[len--]=yushu;//这一步不是很明白 return c; }
code
#include <stdio.h> #include<cstring> //#include<bits/stdc++.h> struct bignum{ int d[1000]; int len; bignum() { len=0; memset(d,0,sizeof(d)); } }; bignum add(bignum a,bignum b) { bignum c; int jinwei=0; for(int i=0;i<a.len || i<b.len;i++) { int temp=a.d[i]+b.d[i]+jinwei; c.d[c.len++]=temp%10; jinwei=temp/10; } if(jinwei!=0) { c.d[c.len++]=jinwei; } return c; } bignum mul(bignum a,int b) { bignum c; int jinwei=0; for(int i=0;i<a.len;i++) { int temp=a.d[i]*b+jinwei; c.d[c.len++]=temp%10; jinwei=temp/10; } while(jinwei!=0) { c.d[c.len++]=jinwei%10; jinwei/=10; } return c; } //void print(bignum a) //{ // for(int i=a.len-1;i>=0;i--) // { // printf("%d",a.d[i]); // } //} int main () { int n; scanf("%d",&n); bignum a,sum; a.d[0]=1; a.len=1; for(int i=1;i<=n;i++) { a=mul(a,i);//这里就相当于上面的a=a*i;只是由于a太大,所以得用高精度表示 sum=add(sum,a); } for(int i=sum.len-1;i>=0;i--) { printf("%d",sum.d[i]); } //print(sum); return 0; }
小结
把以前没怎么学好的高精度捡起来再学了一下,发现网上的教程基本上都能看懂了,感觉学一下算法还是蛮有意思的吧,挺能锻炼自己的思维。这道题目的话只用到了高精度×低精度的情况,可能后面还会遇到高精度×高精度的情况,或者是高精度除法,以后遇到的时候,再继续学一下吧。
参考文章
https://blog.csdn.net/qq_46702358/article/details/120225315?spm=1001.2014.3001.5501
本文作者:Jinx8823
本文链接:https://www.cnblogs.com/Jinx8823/p/16890169.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步