移位运算

a ^ b

题目大意

a a a b b b 次方对 p p p 取模,其中 1 ≤ a , b , p ≤ 1 0 9 1 \leq a,b,p \leq 10 ^ 9 1a,b,p109

思路

根据数学常识,每一个正整数都可以为一的表示为若干指数不重复的 2 2 2 的次幂的和 b = c k − 1 2 k − 1 + c k − 2 2 k − 2 + … … + c 0 2 0 b = c_{k-1}2^{k-1} + c_{k-2}2^{k-2} + …… + c_02^0 b=ck12k1+ck22k2+……+c020 c i c_i ci 表示在二进制下 b b b 的第 i i i 位是 0 0 0 还是 1 1 1

时间复杂度

因为 k = ⌈ l o g ( b + 1 ) ⌉ k = \lceil log(b + 1) \rceil k=log(b+1)⌉ ,通过 k k k 次递推出每一个乘积项,因此整个算法的时间复杂度为 l o g 2 b log_2b log2b

代码

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

typedef long long LL;

const int N = 1e5 + 10;
 
pair<string,int> a[N];
int m,n;

int main()
{
	int a,b,p;
	cin >> a >> b >> p;
	LL ans = 1 % p;
	
	for( ; b; b >>= 1){
		if(b & 1){
			ans = (LL)ans * a % p;// a ^ b 
		}
		a = (LL)a * a % p;
	}
	cout << ans << endl;
	return 0;
}

64位整数乘法

题目大意

a a a b b b p p p 的取模,其中 1 ≤ a , b , p ≤ 1 0 18 1 \leq a,b,p \leq 10 ^ {18} 1a,b,p1018

解法 1 1 1

思路

类似于快速幂的思想,把整数 b b b 用二进制表示, b = c k − 1 2 k − 1 + c k − 2 2 k − 2 + … … + c 0 2 0 b = c_{k-1}2^{k-1} + c_{k-2}2^{k-2} + …… + c_02^0 b=ck12k1+ck22k2+……+c020,则 a ∗ b = a ∗ ( c k − 1 2 k − 1 + c k − 2 2 k − 2 + … … + c 0 2 0 ) a * b = a * (c_{k-1}2^{k-1} + c_{k-2}2^{k-2} + …… + c_02^0) ab=a(ck12k1+ck22k2+……+c020)

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

typedef long long LL;

const int N = 1e5 + 10;
 
pair<string,int> a[N];
int m,n;

int main()
{
	LL a,b,p;
	cin >> a >> b >> p;
	LL ans = 0;
	for(; b; b >>= 1){
		if(b & 1){
			ans = (ans + a) % p;
		}
		a = a * 2 % p;
	}
	cout << ans << endl;
	return 0;
} 

解法 2 2 2

思路

利用 a ∗ b a * b ab mod p p p = a ∗ b a * b ab - ⌊ a ∗ b / p ⌋ ∗ p \lfloor a * b / p \rfloor * p ab/pp。在 a ∗ b / p a * b / p ab/p 中我们可以用浮点数来执行,因为浮点数的在十进制下的有效数字有 18 、 19 18 、 19 1819 ( 因为相除之后会变成小数点后的位数,足够存储 ) (因为相除之后会变成小数点后的位数,足够存储) (因为相除之后会变成小数点后的位数,足够存储),足够胜任。

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

typedef long long LL;

const int N = 1e5 + 10;
 
pair<string,int> a[N];
int m,n;

int main()
{
	LL a,b,p;
	cin >> a >> b >> p;
	a %= p,b %= p;
	LL c = (long double)a * b / p;
	LL ans = a * b - c * p;
	if(ans < 0) ans += p;
	else if(ans >= p)ans -= p;
	cout << ans << endl;
	return 0;
} 
  • 25
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值