竞赛课第八周(大数计算、快速幂、快速幂做矩阵乘法)

实验内容:

1. 编写两个任意位数的大数相加、相乘的程序,给出计算结果。

【参考代码】

相加

#include <bits/stdc++.h>
using namespace std;

int main()
{
 	string num1, num2, result;
 	cin>>num1>>num2;
 	//翻转
 	reverse(num1.begin(), num1.end());
 	reverse(num2.begin(), num2.end());
 	int minsize = min(num1.size(), num2.size()); //求最短的数字(字符串)长度
 	int maxsize = max(num1.size(), num2.size()); //求最短的数字(字符串)长度
 	int carry = 0; //进位
 	for(int i=0; i<maxsize; i++)
 	{
 		if(i < minsize) 
 		{
 			int temporary = num1[i]-'0'+num2[i]-'0'+carry;
	 		if(temporary >= 10)
	 			carry = 1;
	 		else
	 			carry = 0;
	 		result += (temporary % 10) + '0';
		}
 		
 		if(i >= minsize)
 		{
	 		if(num1.size() > num2.size()) //数字1长度大于数字2
			{
				int temporary = num1[i] - '0' + carry; //通过i控制
				if(temporary >= 10)
		 			carry = 1;
		 		else
		 			carry = 0;
				result += (temporary % 10) + '0';
			}
			else if(num2.size() > num1.size()) //数字2长度大于数字1
			{
				int temporary = num2[i] - '0' + carry; //通过i控制
				if(temporary >= 10)
		 			carry = 1;
		 		else
		 			carry = 0;
				result += (temporary % 10) + '0';
			}
		}	
	}
	
 	if(carry) //数字1长度等于数字2,还有进位
 	{
 		result += carry + '0'; //字符串最后面补1
	}
	reverse(result.begin(), result.end()); //倒回来
	cout << result << endl;
 	return 0;
}

相乘

太麻烦了,不写

2. 利用快速幂进行计算a^{n}

【参考代码】

#include <bits/stdc++.h>
using namespace std;

int a, exponent, p;

// 快速幂算法,计算 (a^exponent) % p
long long fastpow(int a, int exponent, int p)
{
    if(exponent == 0)
        return 1; // 如果指数为0,返回1
    if(exponent == 1)
        return a % p; // 如果指数为1,返回a % p
    // 递归调用fastpow函数,将指数exponent除以2
    long long temporary = fastpow(a, exponent/2, p);
    if(exponent%2 == 0)
        return temporary % p * temporary % p; // 如果指数exponent是偶数,返回temp^2 % p
    else
        return temporary % p*temporary % p*a % p; // 如果指数exponent是奇数,返回temp^2 * a % p
}

int main()
{
    cin>>a>>exponent>>p; // 输入a、exponent和p的值
    cout<<a<<'^'<<exponent<<" mod "<<p<<'='<< fastpow(a,exponent,p) <<endl; // 输出结果
}

3. 利用快速幂进行矩阵乘法运算

【参考代码】

待补充

4. 一只青蛙坐在一个网格图上,行和列都是无限的。行的计数从底部开始1, 2, ⋯,列也是这样。青蛙最初的位置是坐标(sx, sy),旅程开始了。它使用了一种特别的跳跃方法。如果它在坐标(x, y),寻找一个可以被x和y都整除的最小的z,然后向上或向右跳z步,下一步坐标可能是(x+z, y)或(x, y+z)。经过有限跳跃后(可能是0步),它停在(ex, ey)。然而,它太累了,忘记了它的起始位置。如果一个个去检查网格的所有坐标,那太笨了!请告诉青蛙一个聪明的办法,到达(ex, ey)的可能的起始位置有多少个?

【参考代码】

#include <bits/stdc++.h>
using namespace std;
/*
推导起点:
x = pt = ex
y = qt = ey*t/(ex+t)
化简:q = ey/(ex+1)
*/
int main()
{
 	int ex, ey, times;
 	cin>>times;
 	while(times--)
 	{
 		cin>>ex>>ey;
 		int ans = 1; //终点也是起点
	 	while(true)
	 	{
	 		if(ex > ey)
	 			swap(ex, ey);
	 		int t = __gcd(ex, ey);
	 		ex = ex/t, ey = ey/t; //求p,q
	 		if(ey % (ex+1) == 0) //判断新的x,y是否符合公式:q = ey/(ex+1)
	 		{
	 			ans++; //有跳跃
	 			ey = ey / (ex+1);
			}
			else
				break;
		}
	 	cout << "result:" << ans << endl;
	}
 	return 0;
}

/*
3
6 10
6 8
2 8
output:
1
2
3
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值