高精度计算+快速幂算法
一.高精度计算:
1.字符串相加(leetcode415)
给定两个字符串形式的非负整数 num1
和num2
,计算它们的和并同样以字符串形式返回。
你不能使用任何內建的用于处理大整数的库(比如 BigInteger
), 也不能直接将输入的字符串转换为整数形式。
示例 1:
输入:num1 = "11", num2 = "123" 输出:"134"
示例 2:
输入:num1 = "456", num2 = "77" 输出:"533"
示例 3:
输入:num1 = "0", num2 = "0" 输出:"0"
提示:
1 <= num1.length, num2.length <= 104
num1
和num2
都只包含数字0-9
num1
和num2
都不包含任何前导零
代码:
class Solution {
public:string addStrings(string num1, string num2) {//给定两个字符串int i=num1.size()-1;int j=num2.size()-1;//从右向左数int add=0;//add:进位string str;while(i>=0||j>=0||add!=0){int x=(i>=0?num1[i]-'0':0);//如果i(j)大于等于0,说明num1[i](num2[j])存在。如果不存在就补0int y=(j>=0?num2[j]-'0':0);//字符-'0'可以实现字符转化为数字,注意:如果是字符串转数字可以使用stoi(),这里不行;
//数字+'0'可以实现数字转化为字符,数字转字符串可以使用to_string()函数int result=x+y+add;str+=(result%10+'0');add=result/10;i--;j--;}reverse(str.begin(),str.end());return str;}
};
2.字符串相乘(leetcode43)
给定两个以字符串形式表示的非负整数 num1
和 num2
,返回 num1
和 num2
的乘积,它们的乘积也表示为字符串形式。
注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。
示例 1:
输入: num1 = "2", num2 = "3" 输出: "6"
示例 2:
输入: num1 = "123", num2 = "456" 输出: "56088"
提示:
1 <= num1.length, num2.length <= 200
num1
和num2
只能由数字组成。num1
和num2
都不包含任何前导零,除了数字0本身。
代码:
class Solution {
public:
string add_sum(string ans,string str){//字符串求和操作,代码与上一题完全相同int i=ans.size()-1;int j=str.size()-1;int add=0;string str1;while(i>=0||j>=0||add!=0){int x=(i>=0?ans[i]-'0':0);int y=(j>=0?str[j]-'0':0);int result=x+y+add;str1+=result%10+'0';add=result/10;i--;j--;}reverse(str1.begin(),str1.end());return str1;
}string multiply(string num1, string num2) {//字符串相乘操作int n=num1.size()-1;int m=num2.size()-1;if(num1=="0"||num2=="0"){//特判,如果num1和num2有一个是“0”,直接返回“0”即可return "0";}string ans;for(int i=n;i>=0;i--){int x=num1[i]-'0';int add=0;string str;//这里需要注意,x,add,str完成一次循环都需要更新。for(int j=n;j>i;j--){str+='0';//这里进行补0操作,注意补0的数目。
//为什么补0?例如:123*456 123*6=738;123*5=615+0(补上一个0),这样在计算相加操作时就是
// +738
// 6150
// =6888模拟乘法计算原则}for(int j=m;j>=0;j--){int y=num2[j]-'0';int result=x*y+add;str+=(result%10+'0');add=result/10;}while(add!=0){str+=(add%10+'0');add/=10;}reverse(str.begin(),str.end());//这个经常漏掉ans=add_sum(ans,str);}return ans;}
};
3.2的N次幂(MT2196)
任意给定一个正整数N(N≤100),计算2的N次方的值。
格式
输入格式:
输入一个正整数N。
输出格式:
输出2的N次方的值。
样例 1
输入:
5
输出:
32
代码:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
using ll = long long;
string add_sum(string ans, string str) {int i = ans.size() - 1;int j = str.size() - 1;int add = 0;string str1;while (i >= 0 || j >= 0 || add != 0) {int x = (i >= 0 ? ans[i] - '0' : 0);int y = (j >= 0 ? str[j] - '0' : 0);int result = x + y + add;str1 += result % 10 + '0';add = result / 10;i--; j--;}reverse(str1.begin(), str1.end());return str1;
}
string multiply(string num1, string num2) {int n = num1.size() - 1;int m = num2.size() - 1;if (num1 == "0" || num2 == "0") {return "0";}string ans;for (int i = n; i >= 0; i--) {int x = num1[i] - '0';int add = 0;string str;for (int j = n; j > i; j--) {str += '0';}for (int j = m; j >= 0; j--) {int y = num2[j] - '0';int result = x * y + add;str += (result % 10 + '0');add = result / 10;}while (add != 0) {str += (add % 10 + '0');add /= 10;}reverse(str.begin(), str.end());ans = add_sum(ans, str);}return ans;
}
void solve() {int n; cin >> n;n--;string num1 = "2", num2 = "2";while (n--) {num1 = multiply(num1, num2);}cout << num1 << endl;
}
signed main() {solve();return 0;
}
二.快速幂算法:
1.【模板】快速幂(洛谷p1226)
题目描述
给你三个整数 a,b,p,求 abmodp。
输入格式
输入只有一行三个整数,分别代表 a,b,p。
输出格式
输出一行一个字符串 a^b mod p=s
,其中 a,b,p 分别为题目给定的值, s 为运算结果。
输入输出样例
输入 #1
2 10 9
输出 #1
2^10 mod 9=7
说明/提示
样例解释
2^10=1024,1024mod9=7。
数据规模与约定
对于 100% 的数据,保证 0≤a,b<2^31,a+b>0,2≤p<2^31。
代码:
#include<iostream>
#include<vector>
#include<algorithm>
#include<numeric>
#include<cmath>
using namespace std;
using ll = long long;
void solve() {ll a, b, p;cin >> a >> b >> p;ll m, n, k;m = a; n = b; k = p;ll ans = 1;while (b) {if (b & 1) {ans = (ans * a) % p;}b /=2;a = (a * a) % p;}cout << m << '^' << n << ' ' << "mod" << ' ' << k << '=' << ans << endl;
}
signed main() {int t=1;while (t--)solve();return 0;
}
2.快速幂(MT2200)
和上一道题完全一样
给你三个整数 a,b,c让你求出 a*b mod c。
代码:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
using ll = long long;
void solve() {ll a, b, c;cin >> a >> b >> c;ll ans = 1;while (b) {if (b & 1) {ans = (a * ans)%c;}a = (a * a) % c;b /= 2;}cout << ans << endl;
}
signed main() {solve();return 0;
}
3.进行一个幂的运算(MT2199)
给出m和k,求m的2^k−1次幂。答案对100000007取模。
格式
输入格式:
两个整数m,k意义如题所示。
输出格式:
一个整数表示答案。
样例 1
输入:
5 3
输出:
78125
备注
其中:1≤m≤100000,0≤k≤1000000
代码:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
using ll = long long;
#define mod 100000007
void solve() {ll m, k; cin >> m >> k;//2^k-1必为奇数ll ans = 1;while (k--) {//这里2^k-1=1+2+4+8+....+2^(k-1)ans = (ans * m) % mod;m = m * m % mod;}cout << ans << endl;
}
signed main() {solve();return 0;
}