P1226 【模板】快速幂||取余运算


原题链接

P1226
题目类型: 普 及 − {\color{orange} 普及-}
AC记录:Accepted

题目大意

给你三个数 a , b , p a,b,p a,b,p,求出 a b   %   p a^b\ \%\ p ab % p的结果。
输出格式为a^b mod p=s,其中 a , b , p a,b,p a,b,p如上, s s s为计算的结果。
S a m p l e \mathbf{Sample} Sample I n p u t \mathbf{Input} Input

2 10 9

S a m p l e \mathbf{Sample} Sample O u t p u t \mathbf{Output} Output

2^10 mod 9=7

H i n t & E x p l a i n \mathbf{Hint\&Explain} Hint&Explain
2 10 = 1024 , 1024 m o d    9 = 7 2^{10}=1024,1024\mod 9=7 210=10241024mod9=7

数据范围

对于 100 % 100\% 100%的数据,保证 0 ≤ a , b < 2 31 , a + b > 0 , 2 ≤ p < 2 31 0\le a,b<2^{31},a+b>0,2\le p <2^{31} 0a,b<231a+b>02p<231

解题思路

看看数据,直接做肯定会溢出,正确的做法是用二进制来做。


我们可以把 b b b化为二进制,将原本的 a b a^b ab看成若干个互不相同的 a a a 2 k 2^k 2k次方相乘得到的结果,如:
             ( 10 ) 10 = ( 1010 ) 2                                                                                               a 10 = ( 1 × a 8 ) × ( 0 × a 4 ) × ( 1 × a 2 ) × ( 0 × a 1 )                          = a 8 × a 2                                                                \ \ \ \ \ \ \ \ \ \ \ \ (10)_{10}=(1010)_2\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ \ \\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ a^{10}= ( 1\times a^8 ) \times ( 0\times a^4 ) \times ( 1\times a^2 ) \times ( 0\times a^1 ) \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\ =a^8 \times a^2 \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \             (10)10=(1010)2                                                                                           a10=(1×a8)×(0×a4)×(1×a2)×(0×a1)                        =a8×a2                                                              

由于每一笔运算的结果都有一个 p p p在限制运算结果的上限,所以在这里的每一笔运算都不会溢出。


但这里还有一个问题, b b b的最大值为 2 31 − 1 2^{31}-1 2311,如果手动存储 2 k 2^k 2k得到的结果,再运算 a 2 k a^{2^k} a2k的值还是拿不到满分,因为最大 a k a^k ak的值为 a 2 30 a^{2^{30}} a230,需要运行 2 30 2^{30} 230次,这个时间肯定会超时,所以这里有一个小技巧:
我们已知: a b × a c = a b + c 那么 ( a 2 i ) 2 = ( a 2 i ) × ( a 2 i ) = a 2 i + 2 i = a 2 i × 2 = a 2 i + 1 \text{我们已知:}a^b \times a^c=a^{b+c} \\ \text{那么}\left( a^{2^i} \right)^2=\left( a^{2^i} \right) \times \left( a^{2^i} \right)=a^{2^i+2^i}=a^{2^i\times2}=a^{2^{i+1}} 我们已知:ab×ac=ab+c那么(a2i)2=(a2i)×(a2i)=a2i+2i=a2i×2=a2i+1
由上面的公式,我们可以只存储 a a a的值,当进入到下一位的时候,我们就将 a a a设为 a × a   %   p a\times a \ \% \ p a×a % p,这样就可以解决了。


最后,祝大家早日
请添加图片描述

上代码

#include<iostream>

using namespace std;

typedef unsigned long long ull;
typedef long long ll;

void POWER_AND_PRINT(ull a,ull b,ull p)
{
	ull initA=a,initB=b;
	
	ull ans=1%p;
	
	a%=p;
	
	for(; b; b>>=1)
	{
		if(b&1) ans=(ull)ans*a%p;
		
		a=(ull)a*a%p;
	}
		
	cout<<initA<<"^"<<initB<<" mod "<<p<<"="<<ans<<endl;
}

int main()
{
    ull n,m,k;
    
    cin>>n>>m>>k;

    POWER_AND_PRINT(n,m,k);

    return 0;
}

完美切题 ∼ \sim

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值