• 清北学堂——1day


    一.

    数学基础知识:

    1°:模运算:

          a=k*b+r     a mod b =r

          (a±b) mod p=(a mod p+b mod p) mod p;

     

    2°:最大公因数与最小公倍数:

          存在g 使得g∣a,g∣b , g=gcd(a,b);

          存在 l 使 a∣l , b∣l ,则l = lcm(a,b)

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

     

    3°:辗转相除法:

          gcd(a,b)=gcd(a,a-b)

          gcd(a,b)=gcd(a,a%b)

          gcd(a,0)=gcd(0,a)=a

     

    4°:进制:

          短除法

     

    5°:高精度运算:

          unsigned int 0~2^32-1

          unsigned long long 0~2^64-1

          

    高精度优化:压位:

    引:k代表每个数组需要压几位

    (1):输入输出:

     1 int k=4;
     2 int base=10000;
     3 char  s[3000]; 
     4 
     5 
     6 struct hpo{
     7     int n;
     8     int  z[256];
     9     hpo(){
    10         n=1;
    11         memset(n,0,sizeof(z));
    12     }
    13     void init()
    14     {
    15          scanf("%s",s+1);
    16          int l=strlen(s+1);
    17          reverse(s+1,s+1+l);
    18          for(int i=1;i<=l;i+=k)
    19          {
    20              n++;
    21              int bit=1;
    22              for(int j=i;j<=i+k-1;j<=l;j++)
    23                  z[n]=z[n]+(s[j]-'0')*bit;
    24                  bit*=10;
    25          }
    26          
    27     } 
    28     void printf()
    29     {
    30         printf("%d",z[n]);
    31         for(int i=n-1;i>=1;i--)
    32             printf("%d"z[i]);
    33     }
    34 };

    (2)高精度加法(压位):

     1 hpo operator+(const hpo &a,const hpo &b)
     2 {
     3     hpo c;
     4     c.n=max(a.n,b.n);
     5     for(int i=1;i<=c.n;i++)
     6         c.z[i]=a.z[i]+b.z[i];
     7     for(int i=1;i<=c.n;i++)
     8     {
     9         c.z[i+1]+=c.z[i]/base;
    10         c.z[i]%=base;
    11     }
    12     if(c.z[c.n+1]!=0) c.n++;
    13     return c;
    14 }

    (3)高精度乘法(压位):

    hpo operator*(const hpo &a,const hpo &b)
    {
        hpo c;
        c.n=a.n+b.n;
        for(int i=1;i<=a.n;i++)
            for(int j=1;j<=b.n;j++)
            c.z[i+j-1]=a.z[i]*b.z[j];
        for(int i=1;i<=c.n;i++)
            {
                c.z[i+1]=c.z[i]/base;
                c.z[i]%=base;
            }
        if(c.z[c.n]==0&&c.n!=1) c.n--;
        return c;
    }

    6°:快速幂:

    1 inline int fast_power(int a,int b,int c){
    2     int ans=1;
    3     while(b){
    4         if(b&1) ans=1ll*a*ans%c;
    5         a=1ll*a*a%c;
    6         b/=2;
    7     }
    8     return ans%c;
    9 } 

    二.

    1°行列式:

    行列式基础知识不再赘述

    简要讲一下

    行列式的消元方法

    共计三种;

    (1)基本消元

    double z[110][110];
    int n;
    
    double gauss()
    {
        double x=1;
        for (int a=1;a<=n;a++)
        {
            for (int b=a;b<=n;b++)
                if (fabs(z[b][a]) > 1e-8)
                {
                    if (b==a) break;
                    x=-x;
                    for (int c=1;c<=n;c++)
                        swap(z[b][c],z[a][c]);
                    break;
                }
            if (fabs(z[a][a]) <= 1e-8) return 0.0;
            for (int b=a+1;b<=n;b++)
            {
                double k = z[b][a] / z[a][a];
                for (int c=1;c<=n;c++)
                    z[b][c] = z[b][c] - z[a][c] * k;
            }
        }
        for (int a=1;a<=n;a++)
            x=x*z[a][a];
        return x;
    }

    (2)主元消元:

     1 double z[110][110];
     2 int n;
     3 
     4 double gauss()
     5 {
     6     double x=1;
     7     for (int a=1;a<=n;a++)
     8     {
     9         for (int b=a+1;b<=n;b++)
    10             if (fabs(z[b][a]) > fabs(z[a][a]))
    11             {
    12                 x=-x;
    13                 for (int c=1;c<=n;c++)
    14                     swap(z[b][c],z[a][c]);
    15             }
    16         if (fabs(z[a][a]) <= 1e-8) return 0.0;
    17         for (int b=a+1;b<=n;b++)
    18         {
    19             double k = z[b][a] / z[a][a];
    20             for (int c=1;c<=n;c++)
    21                 z[b][c] = z[b][c] - z[a][c] * k;
    22         }
    23     }
    24     for (int a=1;a<=n;a++)
    25         x=x*z[a][a];
    26     return x;
    27 }

    (3)辗转相消:

     1 int z[110][110],n;
     2 void gauss()
     3 {
     4     int x=1;
     5     for(int i=1;i<=n;i++)
     6         {
     7             for(int j=i+1;j<=n;j++)
     8                 {
     9                     
    10                     while(z[b][a]!=0){
    11                         int k=z[a][a]/z[b][a];
    12                         for(int u=1;u<=n;u++)
    13                             z[a][u]=z[a][u]-z[b][u]*k;
    14                         for(int u=1;u<=n;u++)
    15                             swap(z[b][v],z[a][v]);
    16                         x=-x;    
    17                             
    18                     }
    19                 }
    20         }
    21     for (int a=1;a<=n;a++)
    22         x=x*z[a][a];
    23     return x;
    24  } 

    在下比较推荐第三种消元方法

    当然我也只会第三种

    相比较来说

    这三种消元方法

    时间复杂度都是O(n^3)

    但相对来说辗转相消没有运行过程中的精度误差

    2°:矩阵

    矩阵基本知识不多说

    矩阵乘法代码:

     1 struct matrix{
     2     int n,m;
     3     int z[256][256];
     4     matrix()
     5     {
     6         n=m=0;
     7         memset(z,0,sizeof(z));
     8     }
     9 }; 
    10 matrix operator(const matrix &a,const matrix &b)
    11 {
    12     matrix c;
    13     c.n=a.n;
    14     c.m=b.m;
    15     for(int i=1;i<=c.n;i++)
    16         for(int j=1;j<=c.m;j++)
    17             for(int l=1;l<=a.m;l++)
    18             c.z[i][j]=c.z[i][j]+a.z[i][k]*b.z[k][j];
    19     return c;
    20 }

    使用矩阵可以进一步的优化程序

    例如;

    斐波那契数列的优化

     1 struct matrix
     2 {
     3     int n,m;
     4     int z[233][233];
     5     matrix()
     6     {
     7         n=m=0;
     8         memset(z,0,sizeof(z));
     9     }
    10 };
    11 
    12 matrix operator*(const matrix &a,const matrix &b)
    13 {
    14     matrix c;
    15     c.n = a.n;
    16     c.m = b.m;
    17     for (int i=1;i<=c.n;i++)
    18         for (int j=1;j<=c.m;j++)
    19             for (int k=1;k<=a.m;k++)
    20                 c.z[i][j] = c.z[i][j] + a.z[i][k] * b.z[k][j];
    21     return c;
    22 }
    23 
    24 
    25 matrix ksm(matrix x,int y)
    26 {
    27     if (y==0) 
    28     {
    29         matrix z;
    30         z.n=z.m=x.n;
    31         for (int a=1;a<=z.n;a++)
    32             z.z[a][a] = 1;
    33         return z;
    34     }
    35     matrix z = ksm(x,y>>1);
    36     z = z*z;
    37     if (y%2==1) z=z*x;
    38     return z;
    39 }
    40 
    41 int main()
    42 {
    43     m1 = [1,0];
    44     m2 = [[1,1],[1,0]];
    45     m1 * ksm(m2,n-1) = [fn,fn-1];
    46 }

    先使用矩阵优化

    简化成:[f(1)  f(0)] * [{1 1} {1 1}]^n-1=[f(n)  f(n-1)]

    之后可以使用快速幂进一步优化

    矩阵还可以用来优化dp

    优化式一定长这样:

    f[i][j]=∑(k)f[i-1][k]*M[k][j]

    不过必须符合以下2个条件

    2:由dp[i-1]->dp[i]

    3:M[k][j]与i无关

    -end-

            

  • 相关阅读:
    html5 本地存储
    javascript 中的 this 关键字详解
    重绘和回流
    javascript 的预解释机制
    zepto.js 实现原理解析
    python3.6新特性
    python面试终极准备
    科大讯飞语音合成api
    智能儿童玩具
    MySQL与MongoDB
  • 原文地址:https://www.cnblogs.com/-Iris-/p/12448089.html
Copyright © 2020-2023  润新知