1.快速幂:
Calculate
R := a ^ n mod m
- #include <stdio.h>
- typedef unsigned long long ULL;
- // 快速模幂计算函数
- ULL powermod(ULL a, ULL n, ULL m)
- {
- ULL res = 1;
- while(n) {
- if(n & 1) { // n % 2 == 1
- res *= a;
- res %= m;
- }
- a *= a;
- a %= m;
- n >>= 1;
- }
- return res;
- }
2.素数判定:
- #include <stdio.h>
- #include <math.h>
- int isprime(int n)
- {
- if(n == 3)
- return 1;
- int temp, i;
- temp = n % 6; // n%6余数有6个:0,1,2,3,4,5,若为0,2,3,4,都不是素数;为1,5,是素数
- if(temp != 1 && temp != 5)
- return 0;
- temp = sqrt(n);
- for(i=3; i<=temp; i+=2)
- if(n % i == 0)
- return 0;
- return 1;
- }
3.筛选法:
- const int N = 1e6;
- const int SQRTN = ceil(sqrt((double) N)); //ceil 返回大于或等于()内值得最小整数
- bool isPrime[N + 1];
- int prefixsum[N + 1];
- bool isPrime[N + 1];
- // Eratosthenes筛选法
- void esieve(void)
- {
- memset(isPrime, true, sizeof(isPrime));
- isPrime[0] = isPrime[1] = false;
- pcount = 0;
- for(int i=2; i<=N; i++) {
- if(isPrime[i]) {
- prime[pcount++] = i;
- for(int j=i*i; j<=N; j+=i) //筛选
- isPrime[j] = false;
- }
- }
- }
4.模除:
斐波拉契数列: F(0) = 7, F(1) = 11, F(n) = F(n-1) + F(n-2) (n>=2)
思想:f(n)(mod 3)≡(f(n-2)+f(n-1))(mod 3)≡(f(n-2)(mod 3) + f(n-1)(mod 3))(mod 3)
若对于正整数k和m,若f(k-2)=f(m-2)且f(k-1)=f(m-1),则f(k)=f(k-2)+f(k-1)=f(m-2)+f(m-1)=f(m),即如果k和m的前两项完全相同,则f(k)=f(m)。这样的数列,若干项之后,其值会循环出现,所以不必将其所有的项都算出来,只需要算出第一个循环的各个项即可。
5.中国剩余定理(孙子定理):
- // 递推法实现扩展欧几里德算法
- long exgcd(long a, long b, long *x, long *y)
- {
- long x0=1, y0=0, x1=0, y1=1;
- long r, q;
- *x=0;
- *y=1;
- r = a % b;
- q = (a - r) / b;
- while(r)
- {
- *x = x0 - q * x1;
- *y = y0 - q * y1;
- x0 = x1;
- y0 = y1;
- x1 = *x;
- y1 = *y;
- a = b;
- b = r;
- r = a % b;
- q = (a - r) / b;
- }
- return b;
- }
- // 扩展欧几里德算法求逆元
- long minv(long a, long p)
- {
- long x, y;
- exgcd(a, p, &x, &y);
- return x<0 ? x+p : x;
- }
- // 试探法求逆元
- long minv2(long a, long p)
- {
- long y=1, t;
- int i;
- if(a < 0) {
- a = a % p;
- a += p;
- }
- for(i=1; i<p; i++) {
- t = a * i;
- if(t % p == 1) {
- y = i;
- return y;
- }
- }
- return y;
- }
- int main(void)
- {
- printf("a=%d m=%d x=%ld x=%ld\n", 65, 83, minv(65, 83), minv2(65, 83));
- printf("a=%d m=%d x=%ld x=%ld\n", 11663, 103, minv(11663, 103), minv2(11663, 103));
- printf("a=%d m=%d x=%ld x=%ld\n", 11227, 107, minv(11227, 107), minv2(11227, 107));
- printf("a=%d m=%d x=%ld x=%ld\n", 11021, 103, minv(11021, 109), minv2(11021, 109));
- // 孙子算经
- long a[] = {2, 3, 2};
- long m[] = {3, 5, 7};
- int i, size= sizeof(a)/sizeof(long);
- long bm=1, subm[size], x=0;
- for(i=0; i<size; i++)
- bm *= m[i];
- for(i=0; i<size; i++)
- subm[i] = bm / m[i];
- for(i=0; i<size; i++) {
- x += subm[i] * minv(subm[i], m[i]) * a[i];
- x %= bm;
- }
- printf("x=%ld\n", x);
- return 0;
- }
6.同余方程:
7.最大公约数,最小公倍数:
http://blog.csdn.net/tigerisland45/article/details/72719362
- #include <stdio.h>
- typedef unsigned long long ULL;
- ULL gcd(ULL m, ULL n)
- {
- return n == 0 ? m : gcd(n, m % n); //求最小公倍数 欧几里得算法
- }
- ULL lcm(ULL m, ULL n)
- {
- return m / gcd(m, n) * n ;
- }