题面:

解题:
暴力相乘?
Absolutely not!b的范围在(0,)间,倘若我们算阶乘每次只乘一个a,那么一共需要运行b次!
显然,我们并不乐意看到计算机劳神伤身地循环b=-1次,于是,我们应当另辟蹊径。
(注:pow函数同样无法通过。)
快速幂
如何通过最少次的计算得到a的最高次幂?这不禁让我们联想到幂的自乘运算:
*
=
*
=
*
=
……………
于是,对于的运算,我们不需要对ans=1进行13次的*a,
而只需要 *
*
即可。
对于,我们选择乘了
、
、
,却没有乘
。
那么,应该如何判断是否应该乘以呢?
不妨将13转化为二进制数:1 1 0 1,
观察可以发现,在二进制中,
分别代表8, 4, 2, 1的位上对应的数分别为:1,1, 0, 1,
因此,二进制第n-1位上的数如果是1,则代表需要乘,反之不需要
不妨用数组t[ ]来存放b的二进制数的每一位,len来记录其位数
如下代码即可求得的值:
long long t[10000] = { 0 };
long long a, b, p;
int ans=1;
//先求出b的二进制数
t[1] = b;
int len = 1; //b二进制数的长度
while (t[len] >= 2) //二进制不允许>=2的数,向后进位
{
t[len + 1] = t[len] / 2;
t[len] %= 2;
len++;
}
long long base = a;
for (int i = 1; i <= len; i++)
{
if (t[i]) //二进制该位为1
{
ans *= base ;
}
base *= base; //自乘
}
取余运算
A×B再取模 = (A取模 × B取模)取模,即:
( A × B ) mod p=[ ( A mod p ) × ( B mod p ) ] mod p
例1:7×7=49 49 % 5=4 等价于 7%5=2 ( 2 * 2 ) % 5 = 4
例2:7×7=49 49 % 9=4 等价于 7%9=7 ( 7 * 7 ) % 9 = 4
对于a和b的数据上限都高达的本题,显然,如果按上述方法计算快速幂,base=a在自乘两次后便可能达到惊人的
=
!不用高精度的话,我们显然无法储存这样庞大的base。
不过,“上帝给人关上一扇门,也一定会给人打开一扇窗”
以上公式给我们一个有力的启示:对乘数base和答案ans都可以: 随 便 Mod !
数据庞大?只需要让mod铺天盖地,巨人也无处遁形:
long long base = a;
base %= p; //base = a本身已经非常庞大了,mod!
for (int i = 1; i <= len; i++)
{
if (t[i]) //二进制该位为1
{
ans = (ans * base) % p; //ans每次累乘后,mod!
}
base = (base % p) * (base % p) % p; //自乘,前mod后mod最后再mod三重保险锁安上
}
AC代码奉上:
#include<iostream>
#include<algorithm>
using namespace std;
long long t[10000] = { 0 };
long long a, b, p;
int ans=1;
int main()
{
cin >> a >> b >> p;
//先求出b的二进制表达
t[1] = b;
int len = 1;
while (t[len] >= 2)
{
t[len + 1] = t[len] / 2;
t[len] %= 2;
len++;
}
long long base = a;
base %= p;
for (int i = 1; i <= len; i++)
{
if (t[i]) //二进制该位为1
{
ans = (ans * base) % p;
}
base = (base % p) * (base % p) % p; //自乘
}
cout <<a<<"^"<<b<<" mod "<<p<<"="<< ans << endl;
return 0;
}