• 数论


    抄袭自 http://www.cnblogs.com/linyujun/

    1.错排原理:

      当考虑第n封信时,若前n-1封信恰有一封正确,  则第n封信的情况为 (n-1)*f(n-2);

              若前n-1封信已经全错排,则任取一封与第n封交换,情况为(n-1)*f(n-1);

      (n-1)*[(f-2)+(f-1)]  [n>2]

    *2.组合数 ,O(n)求

        

    #include<cstdio>
    const int N = 200000 + 5;
    const int MOD = (int)1e9 + 7;
    int F[N], Finv[N], inv[N];//F是阶乘,Finv是逆元的阶乘 
    void init(){
        inv[1] = 1;
        for(int i = 2; i < N; i ++){
            inv[i] = (MOD - MOD / i) * 1ll * inv[MOD % i] % MOD;  //求逆元
        }
        F[0] = Finv[0] = 1;
        for(int i = 1; i < N; i ++){
            F[i] = F[i-1] * 1ll * i % MOD;
            Finv[i] = Finv[i-1] * 1ll * inv[i] % MOD;
        }
    }
    int comb(int n, int m){//comb(n, m)就是C(n, m) 
        if(m < 0 || m > n) return 0;
        return F[n] * 1ll * Finv[n - m] % MOD * Finv[m] % MOD;
    }
    int main(){
        init();
    }

      现在来了新问题,如果n和m很大呢,

      比如求C(n, m) % p  , n<=1e18,m<=1e18,p<=1e5

      卢卡斯定理

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

       1 LL Lucas(LL n, LL m, int p){

       2 return m ? Lucas(n/p, m/p, p) * comb(n%p, m%p, p) % p : 1;

       3 } 

    3杂七杂八.

        acos的使用: hdu 2080,acos求到的是弧度   

          acos(res)*180/PI:

    4.gcd  lcm: 

     1 /*
     2 12 8
     3 8  4
     4 4  0
     5 */
     6 ll gcd(ll a,ll b){    //假设 a > b
     7      return b == 0 ? a : gcd(b,a%b); 
     8 }
     9 ll lcm(ll a,ll b){
    10     return a*b/gcd(a,b);
    11 }

    *5.扩展gcd:

     1 // ax+by = gcd(a, b) = d  已知a,b. 解 x,y,d; 
     2 // b = 0 时:  ax = gcd(a,0) = d;  --> d = a , x = 1 ,y = 0
     3 void ext_gcd(ll a,ll b,ll &x,ll &y,ll &d){
     4     if(!b){
     5         d = a, x = 1 , y = 0;        
     6     }else{
     7         ext_gcd(b,a%b,y,x,d);    // y,x交换位置
     8         y = y - x*(a/b);        // y = y - x*(a/b);
     9     }
    10 }

    &6.数论四大定理:转自  http://www.cnblogs.com/linyujun/p/5194142.html

    (1)威尔逊定理

    若p为质数,则p可整除(p-1)!+1.即  ((p-1)!+1)%p == 0 (p为质数)

    (2)欧拉定理

    欧拉定理:若a,n为正整数,且a,n互素,即gcd(a,n) = 1;
     
    则a^φ(n) ≡ 1 (mod n):    即(a^φ(n))%n = 1;   
     
    φ(n) 欧拉函数是求 1到n-1 中 与n互质的数 的数目
    (3).孙子定理(中国剩余定理)
    (4).费马小定理:
    p是质数,
    若p不能整除a,  则 a^(p-1) ≡1(mod p) 若 a%p!=0  则 (a^(p-1))%p == 1 
    若p能整除a,     则 a^(p-1) ≡0(mod p) 若 a%p==0 则 (a^(p-1))%p == 0
     
    7.模运算:
      
     
         (a  /  b) % p = (a * inv(a) ) % p = (a % p * inv(a) % p) % p
          (a / b)%p = (a*(a的逆元))%p
     
        
        大数取模
        
    1 void BigNumberMod(const char str[],int m){
    2     int ans = 0;
    3     int len = strlen(str);
    4     for(int i = 0 ; i < len ; i ++)
    5         ans = (int)(((long long)ans*10+str[i]-'0')%m);
    6     printf("%d
    ",ans);
    7 }
    *8.线性模方程 和 逆元
        (1)a=b(mod n) a和b关于 n 同余, 即   a mod n == b mod n

        其充要条件为  (a-b)%mod n == 0

              例:求解 ax=b(mod n)

              因为由充要条件得 (ax-b) % n == 0 ---> ax-b = ny  ---->   ax-ny = b

        (2)ax=1(mod n)解x称为 a 关于模n 的逆,当gcd(a,n)=1时(即a,n互质),方程有唯一解,否则无解
           1.同上:  (ax-1)% n ==0   --->   ax-1 == ny  ---->  ax-ny == 1 == gcd(a,n);
            即 ext_gcd(a,n,x,y,d); 当 d != 1时,方程无解
             2. a^(n-2) ≡ inv(a) (mod n)
           3.
              当n是个质数的时候有
              inv(a) = (n - n / a) * inv(n % a) % n
      
     1 #include<cstdio>
     2 typedef long long LL;
     3 LL inv(LL t, LL p) {//求t关于p的逆元,注意:t要小于p,最好传参前先把t%p一下 
     4     return t == 1 ? 1 : (p - p / t) * inv(p % t, p) % p;
     5 }
     6 int main(){
     7     LL a, p;
     8     while(~scanf("%lld%lld", &a, &p)){
     9         printf("%lld
    ", inv(a%p, p));
    10     }
    11 }
     1 #include<cstdio>
     2 const int N = 200000 + 5;
     3 const int MOD = (int)1e9 + 7;
     4 int inv[N];
     5 int init(){
     6     inv[1] = 1;
     7     for(int i = 2; i < N; i ++){
     8         inv[i] = (MOD - MOD / i) * 1ll * inv[MOD % i] % MOD;
     9     }
    10 }
    11 int main(){
    12     init();
    13 }
     
    9.欧拉函数的实现φ(x) 表示 1~x-1中与x互质的数   φ(12):与12互质的数有 3 5 7 11 ,其中φ(1)=1
        
        φ(12)->  12 = 2 * 2 * 3;
        12个数中 删去 2 4 6 8 10 12 3 6 9 12  + 回重复的(3,6两个数字)(容斥) = 4
        

        简便方法:φ(30)的计算方法就是先找30的质因数分别是2,3,5

          φ(30) = 30* 1/2 * 2/3 * 4/5就搞定了

        

    //φ(30) = 30* 1/2 * 2/3 * 4/5就搞定了
    //   30  = 2 * 3 * 5;
    int phi(int x){
        int ans = x;
        for(int i = 2; i*i <= x; i++){
            if(x % i == 0){
                ans = ans / i * (i-1);
                while(x % i == 0) x /= i;
            }
        }
        if(x > 1) ans = ans / x * (x-1);  // x = 31时,1-30都与其互质
        return ans;
    }
    求n个数的欧拉函数:
     1 #include<cstdio>
     2 const int N = 100000 + 5;
     3 int phi[N];
     4 void Euler(){
     5     phi[1] = 1;
     6     for(int i = 2; i < N; i ++){
     7         if(!phi[i]){
     8             for(int j = i; j < N; j += i){
     9                 if(!phi[j]) phi[j] = j;
    10                 phi[j] = phi[j] / i * (i-1);
    11             }
    12         }
    13     }
    14 }
    15 int main(){
    16     Euler();
    17 }

    有其它性质

      p为质数

      1. phi(p)=p-1   

      2. 如果i mod p = 0, 那么 phi(i * p)=phi(i) * p         

      3.若i mod p ≠0,  那么 phi( i * p )=phi(i) * ( p-1 )   

      另:在 a与p互质的情况下  
        
     
    10.中国剩余定理:
        a*x  = 1 (mod p) :x是a关于p的逆元    x = inv(a,p);

        问题:一堆物品

            3个3个分剩2个(x%3==2)   5个5个分剩3个      7个7个分剩2个

            问这个物品有多少个

                 构造                  *剩余的数

              5*7*inv(5*7,  3) % 3  =  1    -->  2*5*7*inv(5*7,  3) % 3  =  2*1

              3*7*inv(3*7,  5) % 5  =  1    -->  3*3*7*inv(3*7,  5) % 5  =  3*1

              3*5*inv(3*5,  7) % 7  =  1    --> 

            令   a = 2 * 5*7*inv(5*7,  3)     b = 3 * 3*7*inv(3*7,  5)     c = 2 * 3*5*inv(3*5,  7) 

            那么  a % 3 = 2            b % 5 = 3            c % 7 = 2

            其实答案就是a+b+c

     
    11.康托展开:用最少空间保存所有状态
          康托展开的公式是 X=a0*(n-1)!+a1*(n-2)!+......
        编码
           其中,ai为从i开始到最后是排在第几个大的(从0开始)。
          X(1,2,3,4): a0 = 0  a1 = 0  a2 = 0  a3 = 0    X = 0
          X(3,4,1,2): a0 = 2  a1 = 2  a2 = 1  a3 = 0    X = 17 = 2*3! + 2*2!+1*1
         解码  
          17% 3!= 2....5    //1.2.3.4 有4位  老二为3
          5%2!  = 2 ....1    //1.2.4      老二为4 
          1%1!  = 1 ....0    //....
                 0        //....
     练习:hdu1430,hdu1043 
     1 void cantor(int s[], LL num, int k){//康托展开,把一个数字num展开成一个数组s,k是数组长度
     2     int t;
     3     bool h[k];//0到k-1,表示是否出现过 
     4     memset(h, 0, sizeof(h)); 
     5     for(int i = 0; i < k; i ++){
     6         t = num / fac[k-i-1];
     7         num = num % fac[k-i-1];
     8         for(int j = 0, pos = 0; ; j ++, pos ++){
     9             if(h[pos]) j --;
    10             if(j == t){
    11                 h[pos] = true;
    12                 s[i] = pos + 1;
    13                 break;
    14             }
    15         }
    16     }
    17 }
    18 void inv_cantor(int s[], LL &num, int k){//康托逆展开,把一个数组s换算成一个数字num 
    19     int cnt;
    20     num = 0;
    21     for(int i = 0; i < k; i ++){
    22         cnt = 0;
    23         for(int j = i + 1; j < k; j ++){
    24             if(s[i] > s[j]) cnt ++;//判断几个数小于它
    25         }
    26         num += fac[k-i-1] * cnt;
    27     }
    28 }
    12.
     
    13.
     
    14.
     
    15.
     
    16.
     
    17.
     
    18.
     
    19.
     
    20.
     
     
     
     
  • 相关阅读:
    HTTP/2之服务器推送(Server Push)最佳实践
    相似人群画像算法
    Linux也有后悔药,五种方案快速恢复你的系统
    IPv6原理、应用与实践
    护航者,腾讯云: 2017年度游戏行业DDoS态势报告—回溯与前瞻
    放大倍数超5万倍的Memcached DDoS反射攻击,怎么破?
    Unity引擎与C#脚本简介
    腾讯云Redis混合存储版重磅推出,万字长文助你破解缓存难题!
    拒绝平庸,以程序员的名义定义新桌面!
    腾讯云EMR大数据实时OLAP分析案例解析
  • 原文地址:https://www.cnblogs.com/zstu-jack/p/5287531.html
Copyright © 2020-2023  润新知