求2的n次方对1e9+7的模

问题引出

有如下问题:
2 n 2^n 2n mod (1e9+7),其中1< n < 1 0 100000 10^{100000} 10100000

首先明确一下此类问题的几种算法,首先朴素算法,即暴力循环求解,是O(N)复杂度,适用范围应该是n小于1000000;然后是快速幂算法,效率是O(log N),适用于n小于 2 100000 2^{100000} 2100000 级别的;然后就是上面的例题了,由于范围是 1 0 100000 10^{100000} 10100000 ,即使是快速幂也不可能在期望时间内解决,这时候需要另辟蹊径。

费马小定理

对于质数P,任意的自然数a,有: a p ≡ a ( m o d   p ) a^p \equiv a (mod \,p) apa(modp)

主要思路

回到上述例题,可知 P 即1e9+7,这是个素数,满足费马小定理的条件。那么我们想提高 2^n 计算的效率,就绕不开减小 n 的大小,我们接下来就利用费马小定理来减少幂 n 的大小。

首先费马小定理的一个小变形: a ( P − 1 ) ≡ 1 ( m o d   P ) a^{(P-1)} \equiv 1 (mod \,P) a(P1)1(modP) ,这个变形的前提是 a 不是 P 的倍数。

而 a 是 2 ,很明显 2 也是素数,所以GCD(a , P ) = 1,接下来对 2^n 进行变形: 2 n = 2 x ∗ ( P − 1 ) ∗ 2 k 2^n = 2^{x*(P-1)}* 2^k 2n=2x(P1)2k,而根据费马小定理,显然 2 x ∗ ( P − 1 ) m o d   P = 1 m o d   P 2^{x*(P-1)} mod\,P = 1 mod \,P 2x(P1)modP=1modP,于是 2 n m o d   P = 2 k 2^n mod\,P= 2^k 2nmodP=2k,其中 k = n%(P-1)。此时 k 小于P,即小于 1e9+7,可以使用快速幂解决。

注意: 值得注意的是,10^100000 最大是1后面有100000个0,需要用字符串存,在转化为整数时利用模运算规则,边转化边取模。

代码示例
#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
const int M = 1e9+7;
typedef long long ll;
ll qpow(ll a,ll b){
	ll res = 1;
	while(b){
		if(b&1) res = res*a%M;
		a = a*a%M;
		b >>= 1;
	}
	return res;	
}
ll solve(string x){
	ll M1 = M-1;
	ll k = x[0]-'0';
	for(int i = 1;x[i];i++) k = (k*10+x[i]-'0')%M1;
	ll ans = qpow(2,k); 
	return ans%M;
}
int main(){
	string n;
	while(cin >> n && n != "0"){
		printf("%lld\n",solve(n));
	}
	return 0;
}

问题拓展

a b m o d P a^b mod P abmodP 的值,其中 P 为质数,a 为整数,并且 b 是位数小于2000的整数。

解题思路

由欧拉定理可得 a φ ( P ) ≡ 1 ( m o d P ) a^{\varphi(P)} \equiv 1 (mod P) aφ(P)1(modP) ,欧拉定理成立的条件只要求 a 与 P 互质即可。

若 a 与 P 不互质,将 a 拆分为若干素因数的乘积,即 a = P k 0 p 1 k 1 p 2 k 2 . . p m k m a = P^{k_0} p_1^{k_1}p_2^{k_2}..p_m^{k_m} a=Pk0p1k1p2k2..pmkm 这时候 a 的质因数里一定存在 P ,剩下的质因数都与 P 互质。而 P k 0 m o d P ≡ 1 ( m o d P ) P^{k_0} mod P \equiv 1 (mod P) Pk0modP1(modP) ,因此质因数 P 对结果无影响,只需考虑剩下的质因数 p 1 k 1 p 2 k 2 . . p m k m p_1^{k_1}p_2^{k_2}..p_m^{k_m} p1k1p2k2..pmkm

p 1 k 1 p 2 k 2 . . p m k m p_1^{k_1}p_2^{k_2}..p_m^{k_m} p1k1p2k2..pmkm 与 P 都是互质的,由欧拉定理可知 a φ ( P ) m o d P = p 1 k 1 φ ( P ) p 2 k 2 φ ( P ) . . p m k m φ ( P ) m o d P ≡ 1 a^{\varphi (P)} mod P = p_1^{{k_1}\varphi(P)}p_2^{{k_2}\varphi(P)}..p_m^{{k_m}\varphi(P)} mod P \equiv 1 aφ(P)modP=p1k1φ(P)p2k2φ(P)..pmkmφ(P)modP1 ,若 b = l φ ( P ) + r b = l\varphi(P) + r b=lφ(P)+r,则 a b m o d P = a r m o d P a^b mod P = a^r mod P abmodP=armodP

综上所述,对于任意的 a,b,P, a b m o d P = a b   m o d φ ( P ) m o d P a^b mod P = a^{b\:mod\varphi(P)} mod P abmodP=abmodφ(P)modP

其中 φ ( P ) \varphi(P) φ(P) 为欧拉函数。

至此解题步骤就清晰了,只需要先让超大数 b 对 φ ( P ) \varphi(P) φ(P) 取模 得到 r,然后计算 a r m o d P a^r mod P armodP 即可。同时可见,求 2 b 2^b 2b 的方法只是一个特例,因为素数 P 的欧拉函数值 φ ( P ) = P − 1 \varphi(P) = P-1 φ(P)=P1

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迷亭1213

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值