GDPU 竞赛技能实践 天码行空8 数学


目的:

(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. 蛙跳

👨‍🏫 评测地址:HDU 5584 LCM Walk
在这里插入图片描述

一只青蛙坐在一个网格图上,行和列都是无限的。行的计数从底部开始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题要做,其他任选两题

  • 25
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值