文章目录
目的:
(1)理解并掌握大数运算
(2)理解并掌握模运算及快速幂运算
(3)理解并熟悉GCD、LCM运算
1. 大数运算
编写两个任意位数的大数相加、相乘的程序,给出计算结果。
💖 Main.java
使用 BigInteger 类
import java.math.BigInteger; // 导入BigInteger类,用于处理大整数运算
import java.util.Scanner; // 导入Scanner类,用于从标准输入读取数据
public class Main
{
public static void main(String[] args) // 主方法,程序的入口点
{
Scanner sc = new Scanner(System.in); // 创建一个Scanner对象,用于从标准输入读取数据
String a = sc.next(); // 读取第一个输入字符串,假设为第一个大整数
String op = sc.next(); // 读取第二个输入字符串,假设为操作符
String b = sc.next(); // 读取第三个输入字符串,假设为第二个大整数
BigInteger aa = new BigInteger(a); // 将字符串a转换为BigInteger对象
BigInteger bb = new BigInteger(b); // 将字符串b转换为BigInteger对象
BigInteger ans = cal(aa, bb, op); // 调用cal方法,传入两个BigInteger对象和操作符
System.out.println("ans = " + ans); // 输出计算结果
}
private static BigInteger cal(BigInteger a, BigInteger b, String op) // 定义一个私有静态方法,用于计算两个BigInteger对象的运算结果
{
BigInteger ans = new BigInteger("-1"); // 初始化结果为-1,用于表示错误或不支持的操作
switch (op) // 根据操作符进行switch-case判断
{
case "*": // 如果操作符是乘号或“×”
case "×": // 注意:这里使用了中文字符“×”,需要确保输入时使用相同的字符
ans = a.multiply(b); // 使用BigInteger的multiply方法进行乘法运算
break;
case "+": // 如果操作符是加号
ans = a.add(b); // 使用BigInteger的add方法进行加法运算
break;
default: // 如果操作符不是乘号或加号
System.err.println("不支持该操作类型"); // 输出错误信息到标准错误输出
break;
}
return ans; // 返回计算结果
}
}
运行结果
💖 Cpp 高精度运算
#include <iostream>
#include <string>
#include <vector>
#include<algorithm>
using namespace std;
// 大数加法
string add(const string& a, const string& b) {
vector<int> result;
int carry = 0;
int i = a.size() - 1, j = b.size() - 1;
while (i >= 0 || j >= 0 || carry) {
int sum = carry;
if (i >= 0) sum += a[i--] - '0';
if (j >= 0) sum += b[j--] - '0';
carry = sum / 10;
result.push_back(sum % 10);
}
string resultStr;
for (int num : result) {
resultStr += to_string(num);
}
reverse(resultStr.begin(),resultStr.end());
// 1234567898765432100
return resultStr;
}
// 大数乘法
string multiply(const string& a, const string& b) {
vector<int> result(a.size() + b.size(), 0);
for (int i = a.size() - 1; i >= 0; --i) {
for (int j = b.size() - 1; j >= 0; --j) {
int sum = result[i + j + 1] + (a[i] - '0') * (b[j] - '0');
result[i + j + 1] = sum % 10;
result[i + j] += sum / 10;
}
}
string resultStr;
for (int i = 0; i < result.size(); ++i) {
if (i == 0 && result[i] == 0) continue; // 跳过前导零
resultStr += to_string(result[i]);
}
return resultStr;
}
int main() {
string num1, num2;
cout << "请输入第一个大数: ";
cin >> num1;
cout << "请输入第二个大数: ";
cin >> num2;
string sum = add(num1, num2);
string product = multiply(num1, num2);
cout << "两数相加的结果是: " << sum << endl;
cout << "两数相乘的结果是: " << product << endl;
return 0;
}
运行结果
2. 快速幂
利用快速幂进行计算 a n a^n an。
💖 Main.java
import java.util.Scanner;
public class Main
{
/**
* 快速幂
*
* @param a 底数
* @param k 幂数
* @return a ^ k = ?
*/
static int qmi(int a, int k)
{
int res = 1;
while (k != 0)
{
if ((k & 1) != 0)
{
res = res * a;
}
k >>= 1;
a = a * a;
}
return res;
}
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
int ans = qmi(a, b);
System.out.println("a ^ b == " + ans);
}
}
运行结果
3. 矩阵乘法
利用快速幂进行矩阵乘法运算
💖 Main.java
// 示例使用
public class Main
{
public static void main(String[] args)
{
int[][] matrix = { { 1, 2 }, { 3, 4 } };
Matrix m = new Matrix(matrix);
// 计算矩阵的平方
Matrix squared = m.power(2);
System.out.println("矩阵的平方:");
squared.print();
// 计算矩阵的立方
Matrix cubed = m.power(3);
System.out.println("矩阵的立方:");
cubed.print();
}
}
class Matrix
{
private int[][] matrix;
public Matrix(int[][] matrix)
{
this.matrix = matrix;
}
// 矩阵乘法
public Matrix multiply(Matrix other)
{
int[][] result = new int[this.matrix.length][other.matrix[0].length];
for (int i = 0; i < this.matrix.length; i++)
{
for (int j = 0; j < other.matrix[0].length; j++)
{
for (int k = 0; k < this.matrix[0].length; k++)
{
result[i][j] += this.matrix[i][k] * other.matrix[k][j];
}
}
}
return new Matrix(result);
}
// 矩阵的幂运算
public Matrix power(int n)
{
Matrix result = new Matrix(new int[this.matrix.length][this.matrix.length]);
for (int i = 0; i < this.matrix.length; i++)
{
result.matrix[i][i] = 1;
}
Matrix base = new Matrix(this.matrix);
while (n > 0)
{
if (n % 2 == 1)
{
result = result.multiply(base);
}
base = base.multiply(base);
n /= 2;
}
return result;
}
// 打印矩阵
public void print()
{
for (int[] row : matrix)
{
for (int val : row)
{
System.out.print(val + " ");
}
System.out.println();
}
}
}
运行结果
4. 蛙跳
一只青蛙坐在一个网格图上,行和列都是无限的。行的计数从底部开始1, 2, ⋯,列也是这样。青蛙最初的位置是坐标(sx, sy),旅程开始了。它使用了一种特别的跳跃方法。如果它在坐标(x, y),寻找一个可以被x和y都整除的最小的z,然后向上或向右跳z步,下一步坐标可能是(x+z, y)或(x, y+z)。经过有限跳跃后(可能是0步),它停在(ex, ey)。然而,它太累了,忘记了它的起始位置。如果一个个去检查网格的所有坐标,那太笨了!请告诉青蛙一个聪明的办法,到达(ex, ey)的可能的起始位置有多少个?
条约的步数:x 和 y 最小公倍数 = x * y / gcd(x,y)
👨🏫 参考题解
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int T = scanner.nextInt();
for (int ca = 1; ca <= T; ca++) {
int x = scanner.nextInt();
int y = scanner.nextInt();
if (x < y) {
int temp = x;
x = y;
y = temp;
}
int cnt = 1;
int k = gcd(x, y);
while (x % (y + k) == 0) {
cnt++;
x = x / (y / k + 1);
if (x < y) {
int temp = x;
x = y;
y = temp;
}
}
System.out.printf("Case #%d: %d\n", ca, cnt);
}
scanner.close();
}
private static int gcd(int a, int b) {
return b != 0 ? gcd(b, a % b) : a;
}
}
5. 埃式筛法
求区间[2, n]内所有的素数对
💖 Main.java
static int cnt;
static int N = 100000010;
static int[] primes = new int[N];
static boolean st[] = new boolean[N];// true 表示合数
static int getPrime(int n)
{
for (int i = 2; i <= n; i++)
{
// st[i] = false 素数
if (!st[i])
{
primes[cnt++] = i;
// 把以素数为因数的数都去掉 2i,3i,4i ...
for (int j = 2; j * i <= n; j++)//条件要控制筛选到 n
{
st[i * j] = true;
}
}
}
return cnt;
}
运行结果
6. 求第1亿个Fibonacci数
应该是矩阵乘法 + 龟速乘法
第4题要做,其他任选两题