知识补充:
- 如果a和b关于m同于,那么(a - b )是m的整数倍。
- 负数取余运算:不同的语言有不同的方法,其中C和JAVA是按第一个数的符号确定结果的符号,C++则要依据系统而定。 取余运算的发展:
1.(a+b)%p=(a%p+b%p)%p2.(a?b)%p=(a%p?b%p)%p
3.(a?b)%p=(a%p?b%p)%p
4.(ab)%p=((a%p)b)%p
- 费马定理:对于一个不能被p整除的数a:
ap≡a mod pap?1≡1 mod p
- 快速幂算法(求xn%mod):
有两种实现方式:
1.二进制实现:
把xn定界化为二进制表示的形式,然后用取余公式实现。如
x22=x2?x4?x16(原理是:22的二进制表示为10110)
然后计算:
( ((x2%mod)?(x4%mod)%mod)?(x16%mod)%mod)%mod2.递归实现(实际是二进制实现倒着的形式):
原理是:如果n是偶数就求(x?x)n/2,这样一直递归下去,直到n/2为0为递归出口。如果n是奇数就求(x?x)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;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-12-18 23:35:17