高精度算法

x33g5p2x  于2022-02-07 转载在 其他  
字(4.0k)|赞(0)|评价(0)|浏览(267)

 

1.高精度实现2的n次方

2.高精度实现阶乘

3.高精度实现加法

4.高精度实现减法

5.高精度实现乘法

6.高精度实现阶乘和

7.高精度计算序列和

1.高精度实现2的n次方

对应牛客网链接:
2的N次方_牛客题霸_牛客网 (nowcoder.com)

题目描述:

解题思路:

由于N的范围较大如果我们采用long long 类型的数字进行存储肯定会栈溢出,因此我们只能使用数组进行模拟也就是高精度。

1.我们将数组的第一个位置和第二个位置设置为1,第一个位置的数字代表长度,第二个位置的数字代表初始值。

1 1

第一次*2:

1 2

第二次*2:

1 4

第三次乘2

1 8

第四次*2

116

此时我们发现16大于10产生了进位,此时我们需要对16进行取余,并且长度+1:

2 6 1

第四次*2:

2 16 2

对16进行取余并进位:

2 6 3

重复上述步骤就完成了模拟了。 

对应代码:

  1. #include<iostream>
  2. #include<vector>
  3. using namespace std;
  4. int main(){
  5. int n;
  6. cin>>n;
  7. vector<int>arr(n);
  8. arr[0]=1;//代表当前长度
  9. arr[1]=1;//代表初始值
  10. for(int i=0;i<n;i++){
  11. int carry=0;//进位
  12. for(int j=1;j<=arr[0];j++){
  13. arr[j]=arr[j]*2+carry;//加上进位
  14. carry=arr[j]/10;//进位
  15. arr[j]%=10;//取余
  16. }
  17. if(carry){//如果有进位
  18. arr[++arr[0]]=carry;//进位不是0就是1
  19. }
  20. }
  21. for(int i=arr[0];i>=1;i--){//反项输出
  22. cout<<arr[i];
  23. }
  24. }

2.高精度实现阶乘

对应牛客网链接:
求整数的阶乘_牛客题霸_牛客网 (nowcoder.com)

题目描述:


  

解题思路:

本题思路和上题基本一样只不过本题每次乘的数不在是2而是i,进位可能不在是10可能会很大,具体请看代码:

对应代码:

  1. #include<iostream>
  2. #include<vector>
  3. using namespace std;
  4. int main(){
  5. int n;
  6. cin>>n;
  7. vector<int>arr(3*n);
  8. arr[0]=1;
  9. arr[1]=1;
  10. for(int i=1;i<=n;i++){
  11. int carry=0;//进位
  12. for(int j=1;j<=arr[0];j++){
  13. arr[j]=arr[j]*i+carry;//每次*i并且加上进位
  14. carry=arr[j]/10;//进位
  15. arr[j]%=10;
  16. }
  17. while(carry){//直到进位为0
  18. arr[++arr[0]]=carry%10;//进位可能很大,超过10
  19. carry/=10;
  20. }
  21. }
  22. for(int i=arr[0];i>=1;i--){//逆序输出
  23. cout<<arr[i];
  24. }
  25. }

 3.高精度实现加法

高精度加法博主之前已经写过了在这里就不写了。

对应链接:

(1249条消息) 加法模板一类题一网打尽_一个山里的少年的博客-CSDN博客

4.高精度实现减法

对应OJ链接:
P2142 高精度减法 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目描述:

高精度实现减法和加法有一点点去别如果第一个数小于第二个数时会出现负数,因此我们默认第一个数比较大,如果第一个数小则交换。在根据小学的减法规则不够就向前借位,具体请看代码

对应代码:

  1. #include<iostream>
  2. #include<string>
  3. #include<vector>
  4. using namespace std;
  5. int main(){
  6. string s1,s2;
  7. cin>>s1>>s2;
  8. if(s1.size()<s2.size()||(s1.size()==s2.size()&&s1<s2)){
  9. //第一数小于第二个数
  10. s1.swap(s2);
  11. cout<<"-";
  12. }
  13. vector<int>a(s1.size()+1);
  14. vector<int>b(s1.size()+1);
  15. vector<int>c(s1.size()+1);
  16. for(int i=0;i<s1.size();i++){
  17. a[s1.size()-i]=s1[i]-'0';
  18. }
  19. for(int i=0;i<s2.size();i++){
  20. b[s2.size()-i]=s2[i]-'0';
  21. }
  22. for(int i=1;i<=s1.size();i++){
  23. if(a[i]<b[i]){//不够减向前借位
  24. a[i+1]--;
  25. a[i]+=10;
  26. }
  27. c[i]=a[i]-b[i];
  28. }
  29. int len=s1.size();
  30. while(c[len]==0&&len>1){//消除前导0
  31. len--;
  32. }
  33. for(int i=len;i>=1;i--){
  34. cout<<c[i];
  35. }
  36. }

5.高精度实现乘法

高精度乘法其实和就是在模拟我们小学时的计算方法:

对应代码:

  1. class Solution {
  2. public:
  3.     string multiply(string num1, string num2) {
  4.         int n1=num1.size();
  5.         int n2=num2.size();
  6.         string res(n1+n2,'0');
  7.         for(int i=n2-1;i>=0;i--){
  8.             for(int j=n1-1;j>=0;j--){
  9.                 int tmp=(res[i+j+1]-'0')+(num1[j]-'0')*(num2[i]-'0');
  10.                 res[i+j+1]=tmp%10+'0';//当前位
  11.                 res[i+j]+=tmp/10; //前一位加上进位,res[i+j]已经初始化为'0',加上int类型自动转化为char,所以此处不加'0'
  12.             }
  13.         }
  14.         
  15. //去除首位的前导零
  16.         for(int i=0;i<n1+n2;i++){
  17.             if(res[i]!='0')
  18.                 return res.substr(i);
  19.         }
  20.         return "0";
  21.        
  22.         
  23.     }
  24. };

6.高精度实现阶乘和

对应OJ链接:
P1009 [NOIP1998 普及组] 阶乘之和 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

解题思路:

解题思路分为两部:

1.现计算阶乘

2.计算和

解题请看代码

对应代码:

  1. #include<vector>
  2. #include<iostream>
  3. using namespace std;
  4. void fact(int n,vector<int>&tmp) {
  5. int carry = 0;//进位
  6. for (int j = 1; j <= tmp[0]; j++) {
  7. tmp[j] = tmp[j] * n + carry;
  8. carry = tmp[j] / 10;
  9. tmp[j] %= 10;
  10. }
  11. while (carry) {
  12. tmp[++tmp[0]] = carry % 10;
  13. carry /= 10;
  14. }
  15. }
  16. void add(vector<int>&sum,vector<int>&tmp) {
  17. if (sum[0] < tmp[0]) {
  18. sum[0] = tmp[0];
  19. }
  20. int carry = 0;//进位
  21. for (int i = 1; i <= sum[0]; i++) {
  22. sum[i] = sum[i] + carry + tmp[i];
  23. carry = sum[i] / 10;
  24. sum[i] %= 10;
  25. }
  26. if (carry) {
  27. sum[++sum[0]] = carry;
  28. }
  29. }
  30. int main() {
  31. int n;
  32. cin >> n;
  33. vector<int>sum(2 * n);
  34. sum[0] = 1;//代表长度;
  35. vector<int>tmp(2 * n);
  36. tmp[0] = 1;//代表长度
  37. tmp[1] = 1;//代表初始值
  38. for (int i = 1; i <= n; i++) {
  39. fact(i,tmp);
  40. add(sum, tmp);
  41. }
  42. for (int i = sum[0]; i >= 1; i--) {
  43. cout << sum[i];
  44. }
  45. return 0;
  46. }

7.高精度计算序列和

对应OJ链接:
题目详情 - 7-38 数列求和-加强版 (20 分) (pintia.cn)

题目描述:

给定某数字A(1≤A≤9)以及非负整数N(0≤N≤100000),求数列之和S=A+AA+AAA+⋯+AA⋯A(N个A)。例如A=1, N=3时,S=1+11+111=123。

输入数字A与非负整数N。

输出其N项数列之和S的值。

  1. 123

解题思路和加法基本一样,老铁可以在纸上画一画。

对应代码:

  1. #include<iostream>
  2. #include<vector>
  3. using namespace std;
  4. int main(){
  5. int n,A;
  6. cin>>A>>n;
  7. if(n==0){
  8. cout<<0;
  9. return 0;
  10. }
  11. long long carry=0;//进位
  12. vector<int>arr(5*n);
  13. int high=0;
  14. int i;
  15. for( i=0;i<n;i++){
  16. arr[i]=((n-i)*A+carry)%10;//取余10;
  17. carry=((n-i)*A+carry)/10;//计算进位
  18. high=i;//记录最高位
  19. }
  20. if(carry){//看是否有进位
  21. arr[i]=carry;
  22. high=i;//修改最高位
  23. }
  24. for(int j=high;j>=0;j--){
  25. cout<<arr[j];
  26. }
  27. }

相关文章