前不久接触了数论,发现。。。。果然数论好难啊!!!!不过还是有一些简单的,首先快速幂及取余是要掌握的,在求幂时,如果用朴素算法,时间是O(n),而快速幂则是O(logn),举个例子,如果用朴素算法计算a^41,就需要做41 次乘法运算。时间复杂度O(n)。
使用分治算法,就有:a ^ 41=(a ^ 20) ^ 2 * a,a ^ 20=(a ^ 10) ^ 2,a ^ 10=(a ^ 5) ^ 2,a5=(a ^ 2) ^ 2 * a,a2=(a)^2。只需7 次乘法运算。时间复杂度O(logn),快速幂有递归形式及非递归形式
a^b的形式,递归版
long long quickpow(long long a, long long b) { if (b == 0) return 1;//a^0 = 1 long long r = quickpow(a, b / 2);//分治 r *= r;//偶次幂 if (b % 2)//如果是奇次幂,还需多乘一次 r = r * a; return r; }
非递归:
long long quickpow(long long a, long long b) { long long d = 1, t = a; while (b > 0) { if (t == 1) return d; if (b % 2) d = d * t; b = b / 2; t = t * t; } return d; }
快速幂取模 a^b % n:
long long quickdiv(long long a, long long b, long long n) { long long d=1, t=a; while (b>0) { if (t==1) return d; if (b%2) d=d*t%n; b=b/2; t=t*t%n; } return d; }
下面是一些题
wikioi1497:http://codevs.cn/problem/1497/
输入b,p,k的值,编程计算bp mod k的值。其中的b,p,k*k为长整型数(2^31范围内)。
b p k
输出b^p mod k=?
=左右没有空格
2 10 9
2^10 mod 9=7
【代码】:


#include<cstdio> #include<iostream> using namespace std; long long b, p, k; long long qpow() { long long a = p; long long d = 1, t = b; while(a > 0) { if(t == 1)return d % k; if(a % 2)d = d * t % k; a = a / 2; t = t * t % k; } return d; } int main() { scanf("%lld%lld%lld", &b, &p, &k); printf("%lld^%lld mod %lld=%lld\n",b,p,k,qpow()); return 0; }
wikioi 2952:http://codevs.cn/problem/2952/
著名生物学家F博士发现了一种单细胞生物。
它长得像蚯蚓,分裂速度极快(每分钟一次),分裂也像蚯蚓一样,断成两段,再长成。
它很好斗,只要q只聚集在一起,就会q只一群打起来,当然都会打死。
假设一开始有1只,求a分钟后有多少只单细胞蚯蚓?
两个正整数A Q
答案
4 5
1
对于50%数据,A<=20,Q<=100.
对于全部数据,A<=2*10^9,Q<=10^8.
【代码】:


#include<cstdio> using namespace std; long long a,q; long long qpow() { long long d = 1, t = 2; while(a > 0) { if(t == 1)return d % q; if(a % 2)d = d * t % q; a /= 2; t = t * t % q; } return d; } int main() { scanf("%lld%lld", &a, &q); printf("%lld",qpow()); return 0; }