快速求幂模

今天我要介绍的是快速求幂模,在开始介绍之前,我们先看看如何快速求幂。这里我要介绍的是二分求幂。

二分求幂的原理如下:

下面,我们将这个公式转换成代码:

int cifang(int a,int n)//返回值是a的n次方
{
    int res=1;//任何数的0次方都等于1,所以初始化为1
    while(n != 0)
    {
        if(n%2 == 1)//如果n是奇数
            res *= a;//就要多乘一次,即res = res*a;
        a = a*a;
        n /= 2;//二分,即n = n/2
    }
    return res;
}

我们都知道计算机是采用二进制计算的,所以如果我们采用二进制计算势必会更快。所以我们可以将上面的代码稍作改动,使用位运算。这里简单介绍一下下面代码使用到的位运算符,便于理解。

&的用法:1 & 1 = 1;1 & 0 = 0;0 & 1 = 0;0 & 0 = 0。

>>的用法:>>表示右移,n>>1:表示n除以21

还有其他的位运算符这里不再详细介绍,有兴趣的可以参见http://baike.baidu.com/view/379209.htm

下面看看代码如何修改:

int cifang(int a,int n)//返回值是a的n次方
{
    int res=1;//任何数的0次方都等于1,所以初始化为1
    while(n != 0)
    {
        if(n&1)//如果n是奇数
            res *= a;//就要多乘一次,即res = res*a;
        a = a*a;
        n >>= 1;//二分,即n = n/2
    }
    return res;
}

那如何快速求幂模呢?先给这么一个公式:(a*b)%p = ( (a%p) * (b%p) ) % p

接下来就不难实现快速求幂模了,下面直接给出代码:

int mimo(int a,int n,int b)//返回值是a的n次方对b取余后的值
{
    int res=1;
    a = a%b;//积的取余等于取余的积取余
    while(n>0)
    {
        if(n & 1)   //是否为奇数
            res = res*a%b;//n是奇数的话就要多乘一次,原理和前面的二分求幂一样
        n >>= 1;//二分,即n = n/2
        a = a*a%b;//积的取余等于取余的积取余
    }
    return res;
}

时间: 2024-07-28 16:07:23

快速求幂模的相关文章

NYOJ--102--次方求模(快速求幂取模)

次方求模 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 求a的b次方对c取余的值 输入 第一行输入一个整数n表示测试数据的组数(n<100)每组测试只有一行,其中有三个正整数a,b,c(1=<a,b,c<=1000000000) 输出 输出a的b次方对c取余之后的结果 样例输入 3 2 3 5 3 100 10 11 12345 12345 样例输出 3 1 10481 1 /* 2 Name: NYOJ--102--次方求模 3 Copyright: ?

A sequence of numbers(快速求幂)

题目描述 Xinlv wrote some sequences on the paper a long time ago, they might be arithmetic or geometric sequences. The numbers are not very clear now, and only the first three numbers of each sequence are recognizable. Xinlv wants to know some numbers in

快速求幂

快速幂在算指数时是很高效的,他的基本原理是二进制. 如果要算 2^5,可以直接2*2*2*2*2 但是如果要算 3^999,指数N太大,计算太慢,所以有一种快速的解法. @@@@@@@@@@@@@@@@@@@@@@@@ 以3^21为例. 2^21=(2^16)×(2^4)×(2^1) 21的二进制可以写成(10101)----------------而10101可以写成1*2^4+0*2^3+1*2^2+0*2^1+1*2^0 可以明显看出, 每一个香对应着上边的指数.   2^4=16 2^2

快速求幂运算笔记

如何快速求x得n次方呢? 首先C++里面有个pow如何实现呢?自己查查,里面使用double,肯定更麻烦,还有jianzhi 我们会顺手写下 int res=1; for(int i=1;i<=n;i++) { res*=x; } 学习一下快速幂,logn内计算出来,使用N的二进制,只需要logN就可以计算. 正要的就是计算每个为1对应的基数.列入: 11是多少?是二进制的话,就是1*2^1+1 那么x^(11)呢,两个1对应的基数是多少呢?低位1对应的是X,高位1对应的是X^2,因此,就是位于

快速求幂 POW优化

#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> using namespace std; int pow(int x, int n) { int result = 1; while (n > 0) { if (n % 2==1) result *= x; x *= x; n /=2 ; } return result; } int main()

非递归快速求幂算法

快速求正整数次幂,当然不能直接死乘.举个例子:3 ^ 999 = 3 * 3 * 3 * … * 3直接乘要做998次乘法.但事实上可以这样做,先求出2^k次幂:3 ^ 2 = 3 * 33 ^ 4 = (3 ^ 2) * (3 ^ 2)3 ^ 8 = (3 ^ 4) * (3 ^ 4)3 ^ 16 = (3 ^ 8) * (3 ^ 8)3 ^ 32 = (3 ^ 16) * (3 ^ 16)3 ^ 64 = (3 ^ 32) * (3 ^ 32)3 ^ 128 = (3 ^ 64) * (3

二分求幂(快速求幂,二进制求幂)

二分求幂, 非递归求法(二进制求法): 比如 2^5就是5个2相乘,按照5的二进制求 3^10就是8个3相乘,再2个3相乘. 处理幂的二进制,具体实现代码如下: long long quickmulti(long long a,long long b) { long long res=1; while(b) { if(b&1) //如果最后一位为1,则res*=a; res*=a; a*=a; //a*=a b>>=1; //b%=2 } return res; }

快速求幂运算

1 #include <stdio.h> 2 #include <math.h> 3 //递归算法 4 int recursion(int a,int b) 5 { 6 int tem = 1; 7 if(b==0)return 1; 8 else if(b==1)return a; 9 tem = recursion(a,b>>1); 10 tem = tem*tem; 11 if(b&1) tem = tem * a; 12 return tem; 13 }

北大ACM3641——Pseudoprime numbers~~快速求幂法

这一题,主要是快速求幂的方法的应用. 可以看看快速求幂方法的原理:http://blog.csdn.net/qq_25425023/article/details/44316463 题目的大概意思是: 输入两个数p,a,p为素数,则直接输出no,否则判断a^p % p == a?等于就yes,不等于就no. 理解了题目的意思,就很容易了. 下面的是AC代码: #include <iostream> #include <cstdio> using namespace std; int