UVa 10006 快速幂运算

来源:互联网 发布:手机淘宝联盟能推广吗 编辑:程序博客网 时间:2024/05/20 03:07

知识补充:


  • 如果a和b关于m同于,那么(a - b )是m的整数倍。
  • 负数取余运算:不同的语言有不同的方法,其中C和JAVA是按第一个数的符号确定结果的符号,C++则要依据系统而定。 取余运算的发展:
    1.(a+b)%p=(a%p+b%p)%p
    2.(ab)%p=(a%pb%p)%p
    3.(ab)%p=(a%pb%p)%p
    4.(ab)%p=((a%p)b)%p
  • 费马定理:对于一个不能被p整除的数a:
    apa mod p
    ap11 mod p
  • 快速幂算法(求xn%mod)

有两种实现方式:
1.二进制实现:
xn定界化为二进制表示的形式,然后用取余公式实现。如

x22=x2x4x162210110

然后计算:
( ((x2%mod)(x4%mod)%mod)(x16%mod)%mod)%mod

2.递归实现(实际是二进制实现倒着的形式):
原理是:如果n是偶数就求(xx)n/2,这样一直递归下去,直到n/2为0为递归出口。如果n是奇数就求(xx)n/2x,这样一直递归下去,直到n/2为0为递归出口。

代码部分:

二进制实现快速幂:

typedef long long LL;LL mod(LL x, LL n, LL mod) {    LL res = 1;    while (n > 0) {        if (n & 1) res = res * (x % mod) % mod;        n >>= 1;        x = x * x;    }    return res;}

递归实现代码

typedef long long LL;LL mod(LL x, LL n, LL mod) {    if (n == 0) return 1;    LL res = mod(x * x % mod, n / 2, mod);    if (n & 1) res = res * x %mod;    return res;}

UVa 10006的代码:

#include <iostream>#include <cmath>#include <algorithm>#include <cstdio>using namespace std;typedef long long LL;LL doit(LL x, LL n, LL mod) {    LL res = 1;    //从2的0次方开始    while (n > 0) {        if (n & 1) res = res * x % mod;        x = x * x % mod;        n >>= 1;    }    return res;}bool isprime(int x) {    for (int i = 2; i * i <= x; i++) {        if (x % i == 0) return false;    }    return x != 1;}int main(void){    int n;    while (scanf("%d", &n), n) {        bool ans = true;        if (isprime(n)) { printf("%d is normal.\n", n); continue; }        for (int i = 2; i < n; i++) {            if (doit(i, n, n) != i) {                ans = false;                break;            }        }        if (ans) printf("The number %d is a Carmichael number.\n", n);        else printf("%d is normal.\n", n);    }    return 0;}
1 0
原创粉丝点击