数论定理篇

真是的,博主本来就菜,又懒得刷题。

只好一边划水,一边从别人的博客上搬代码。

1)素数筛法

2)快速幂,快速乘

快速乘(注意:变乘法为加法):

LL Kmul(LL a, LL b, LL mo){ //计算a*b%mo 
    LL ret = 0;
    while(b){
        if(b & 1) ret = (ret + a) % mo;
        a = (a+a) % mo;
        b >>= 1;
    }
    return ret;
}

    //即每次a乘2,b除2

3)欧几里得求gcd,lcm

递归,gcd(a,b)= gcd(b,a%b) = gcd(x,0) = x

  lcm(a,b)=  a*b/gcd(a,b) = a/gcd(a,b)*b

4)扩展欧几里得

  解决ax+by=c整数解问题

5)费马-欧拉定理

  I、欧拉定理

    若n、a互质,a^φ(n) ≡ 1 (mod n)    //同余式

  II、费马小定理

    若p、a互质,并且p是质数,a^(p-1) ≡1(mod p)

 

  //循环节

6)逆元inv(解决在除法过程中取模问题)

  定义:a*inv(a) ≡ 1 (mod m) 

  根据费马小定理,若m为质数,inv(a)=a^(m-2)   //m尽量取大

          若不是,转换为扩展欧几里得问题

  O(n)求出2->N的逆元(MOD要为质数)

  

int init(){
    inv[1] = 1;
    for(int i = 2; i < N; i ++){
        inv[i] = (MOD - MOD / i) * 1ll * inv[MOD % i] % MOD;
    }
}

  

7)欧拉函数φ(n)或phi(n)

  phi(n)为1-n中与n互质的数的个数

  模仿素数埃筛

  

int phi[N];
void Euler(){
    phi[1] = 1;
    for(int i = 2; i < N; i ++){
        if(!phi[i]){
            for(int j = i; j < N; j += i){
                if(!phi[j]) phi[j] = j;
                phi[j] = phi[j] / i * (i-1);
            }
        }
    }
}

 

8)中国剩余定理

求一个x,模m1余r1,模m2余r2,......

若m1,m2....两两互质,则x有解。

模板代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 typedef long long LL;
 5 typedef pair<LL, LL> PLL;
 6 LL a[100000], b[100000], m[100000];
 7 LL gcd(LL a, LL b){
 8     return b  ? gcd(b, a%b) : a;
 9 }
10 void ex_gcd(LL a, LL b, LL &x, LL &y, LL &d){
11     if (!b) {d = a, x = 1, y = 0;}
12     else{
13         ex_gcd(b, a % b, y, x, d);
14         y -= x * (a / b);
15     }
16 }
17 LL inv(LL t, LL p){
18     LL d, x, y;
19     ex_gcd(t, p, x, y, d);
20     return d == 1  ? (x % p + p) % p : -1;
21 }
22 PLL linear(LL A[], LL B[], LL M[], int n) { 
23     LL x = 0, m = 1;
24     for(int i = 0; i < n; i ++) {
25         LL a = A[i] * m, b = B[i] - A[i]*x, d = gcd(M[i], a);
26         if(b % d != 0)  return PLL(0, -1); 
27         LL t = b/d * inv(a/d, M[i]/d)%(M[i]/d);
28         x = x + m*t;
29         m *= M[i]/d;
30     }
31     x = (x % m + m ) % m;
32     return PLL(x, m);
33 }
34 int main(){
35     int n;
36     while(scanf("%d", &n) != EOF){
37         for(int i = 0; i < n; i ++){
38             a[i] = 1;
39             scanf("%d%d", &m[i], &b[i]);  //分别为m,r
40         }
41         PLL ans = linear(a, b, m, n);
42         if(ans.second == -1) printf("-1\n");
43         else printf("%lld\n", ans.first);
44     }
45 }
View Code

9)大组合数,卢卡斯定理(p为质数)

  C(n, m) % p  =  C(n / p, m / p) * C(n%p, m%p) % p     //递归

10)说到组合,斯特林数,卡特兰数  //数列工具OEIS

  第二类斯特林数:将有n个元素的集合划分成m个集合(没有空集合),有多少种划分,递推式:

  

   另斯特林公式近似求n!:

  

  求n!的位数:   //  (int)lg(n!) + 1 

  

 

  卡特兰数://出栈序列

    其前几项为 : 1, 1, 2, 5, 14, 42, 132, 429,

 

  

    若n次入栈,m次出栈:C(n+m,n)-C(n+m,m-1)

 

posted @ 2018-02-05 16:31  hzhuan  阅读(590)  评论(0编辑  收藏  举报