数学

1.1 排列组合

排列组合主要应用在计数原理的问题上

加法原理:做一件事情,完成它有N类办法,在第一类办法中有M1种不同的方法,在第二类办法中有M2种不同的方法,……,在第N类办法中有M(N)种不同的方法,那么完成这件事情共有M1+M2+……+M(N)种不同的方法 (摘自百度百科)

乘法原理:做一件事,完成它需要分成n个步骤,做第一 步有m1种不同的方法,做第二步有m2不同的方法,……,做第n步有mn不同的方法。那么完成这件事共有 N=m1m2m3…mn 种不同的方法 (摘自百度百科)

排列的定义及其计算公式:从n个不同元素中,任取m(m≤n)个元素按照一定的顺序排成一列,叫做从n个不同元素中取出m个元素的一个排列;从n个不同元素中取出m(m≤n)个元素的所有排列的个数,叫做从n个不同元素中取出m个元素的排列数,用符号 A(n,m)表示 A(n,m)=n(n-1)(n-2)……(n-m+1)= n!/(n-m)! 此外规定0!=1   

组合的定义及其计算公式:从n个不同元素中,任取m(m≤n)个元素并成一组,叫做从n个不同元素中取出m个元素的一个组合;从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数。用符号 C(n,m) 表示 C(n,m)=A(n,m)/m!=n!/((n-m)!*m!);C(n,m)=C(n,n-m)。

环排列:从n个元素中取出m个元素的循环排列数=A(n,m)/m=n!/m(n-m)!.

多组组合:n个元素被分成k类,每类的个数分别是n1,n2,...nk这n个元素的全排列数为 n!/(n1!×n2!×...×nk!).

可重组合: k类元素,每类的个数无限,从中取出m个元素的组合数为C(m+k-1,m)。

该问题可引申到,k个非负整数xi{1<=i<=k}之和为m(m>=0),满足∑{1<=i<=k}xi=m的非负整数解有多少组

如果令yi=xi+1,n=m+k,则还可引申为,k个正整数yi{1<=i<=k}之和为n(n>=k),满足∑{1<=i<=k}yi=n的正整数解有多少组

范德蒙恒等式:对任意0<=k<=n,有C(n,m)=∑{0<=i<=m}C(k,i)C(n-k,m-i)

二项式定理:(x+y)^n =∑{0<=k<=n} C(n,k)x^(n-k)y^k

1.2 递推关系

等差数列的通项公式为:an=a1+(n-1)d

前n项和公式为:Sn=n(a1+an)/2


等比数列(q不为0)的通项公式为:an=a1*q^(n-1)

前n项和公式为:

q不为1 Sn=a1*(1-q^n)/(1-q)

以及q=1 Sn=na1

线性常系数齐次递推关系:∑{0<=i<=k}CiAn-i=0,其中C0=1,并已知Ai(0<=i<k)

则特征方程为,∑{0<=i<=k}Cix^(k-i)=0

设其在复数域内共有m个不同的根,Ri(1<=i<=m),

且Ri是方程的Ji重根,满足∑{1<=i<=m}Ji=k


那么,原递推式通解为:An=∑{1<=i<=m}(Ri^n*∑{0<=j<Ji}Fij*n^j)

其中Fij为待定系数


如若,是非齐次,如∑{0<=i<=k}CiAn-i=G(n),而G(n)是多项式

那么可以将原式反复差分,从而齐次化,再依旧用待定系数法求解



求解一般递推数列中的不动点法

先得到原式的特征方程F(G(x))

然后求解F(G(x))=G(x)的根(简单起见许多时候可以就令G(x)=x)

设跟为a,b,c,d.....


那么很有可能方程可以化成形式是x-a,x-b,x-c,x-d.....等等的整数幂(包括负数幂,就是作分母)的乘积的和

如此再用迭代的方式求出来


1.3 素数
●知识精讲

质数,也称素数,是指因子只有1和其本身的数。对应的,还能被其他整数整除的数称为合数。0和1既不是素数也不是合数。素数在数论中有着举足轻重的地位,在ACM中也常常出现,常见的有判断一个数是否为素数,求某范围内的素数,分解质因数,求因子个数,因子和,以及与其他数论定理相结合的题目等等。

关于素数有许多的构造定理和猜想,详细的资料可自行查询,这里仅对题目中常见的有关素数的应用做简单介绍。


●例题分析

1.判断素数的方法

(1)直接按照定义判断

     bool check(int n)  
     {   
           if (n<=1) return false;   
           if (n==2) return true;   
           for (int i=3; i<=sqrt(n); i+=2)     
                if (n%i==0) 
                   return false;   
            return true;  
      }  

(2)素数筛法

像“筛子”一样将一定范围内的素数筛选出来。

    void Getprime()  
    {   
         memset(prime,0,sizeof(prime));    
         for (int i=3; i<=N; i++)             
               if (i%2==0) prime[i] = false;             
               else prime[i] = true;         
          prime[2] = true;         
          prime[1] = false;         
         for (int i=3; i<=sqrt(N); i+=2)             
             if (prime[i])                 
                 for (int j=i*i; j<N; j+=2*i)                      
                       prime[j] = false;  
     }  

(3)费马小定理测试(定理)

费马小定理:如果p是一个素数,且0<a<p,则a^(p-1)%p=1. 利用费马小定理,对于给定的整数n,可以设计素数判定算法,通过 计算d=a^(n-1)%n来判断n的素性,当d!=1时,n肯定不是素数,当d=1时,n 很可能是素数.

(4)Miller-Rabbin素数测试法

二次探测定理:如果p是一个素数,且0<x<p,则方程x^2%p=1的解为:x=1或x=p-1. 利用二次探测定理,可以再利用费尔马小定理计算a^(n-1)%n的过程 中增加对整数n的二次探测,一旦发现违背二次探测条件,即得出n不是素数的结论.

如果n是大于2的素数,则(n-1)必是偶数,因此可令(n-1)=m*(2^q),其中m是正奇数( 若n是偶数,则上面的m*(2^q)一定可以分解成一个正奇数乘以2的k次方的形式 ),q是非负整数,考察下面的测试: 我们要选择一个随机的整数p (1<=p<=n-1),接下来判断 p^m=1 (mod n),如果成立,我们就说n通过了测试,但是有可能不是素数也能通过测试。所以我们通常要做多次这样的测试,以确保我们得到的是一个素数。Miller 测试进行k次,将合数当成素数处理的错误概率最多不会超过4^(-k).

     bool Miller_rabin(INT n)  
     {     
         if (n==2) return true;     
         if (n<2 || !(n&1)) return false;     //先计算出m、j,使得n-1=m*2^k,其中m是正奇数,k是非负整数     
         INT m = n-1,k = 0;     
         while (!(m&1))
         {         
                k++;         
                m >>= 1;     
         }//得到m,k     
         for (int i=0; i<9; i++)
        {//连续测试         
              if (p[i] >= n) return true;        
              INT u = power_mod(p[i],m,n); //随机取一个p计算 p^m % n      
              If (u == 1) continue; //一组测试完成通过            
              for (int j=0; j<k; j++){         
                  INT buf = product_mod(u,u,n);//计算u*u%n         
                   if (buf==1 && u!=1 && u!=n-1) return false; //二次检测非素数          
                    u = buf;           
                }           
             if (u>1) return false;     
           }     
           return true;  
        }  

2.欧拉函数

对正整数n,欧拉函数φ是少于或等于n的数中与n互质的数的数目。φ函数的值通式:φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn),其中p1, p2……pn为x的所有质因数,x是不为0的整数。φ(1)=1(唯一和1互质的数就是1本身)。若m,n互质,φ(mn)=φ(m)φ(n)。

      int Euler(int n)  
      {        
           int ans = n;        
           for (int i=2; i<=sqrt(n); i++)
           {          
                if (n%i==0)
                {           
                      ans = ans-ans/i;           
                      while (n%i==0) n /= i;         
                  }        
            }        
            if  (n>1) 
                ans = ans-ans/n;        
            return ans;  
       }

1.4 二进制
●知识精讲

进制也就是进位制,是人们规定的一种进位方法。 对于任何一种进制---X进制,就表示某一位置上的数运算时是逢X进一位。在这里主要讨论进制转换和位运算两个问题。

1.进制转换

所谓进制只是一个权重,在A进制下,数字实际值是各位数字的"权值*权重"的累加值。 而"权重"为A的n次方,n代表位数。

用公式来表示就是:

abcd = a * A^3 + b * A^2 + c * A^1 + d * A^0

举个直观的例子来说 在7进制下,数字 1234 的大小应该是 1 * 7^3 + 2 * 7^2 + 3 * 7^1 + 4 * 7^0 =1*343 + 2*49 + 3*7 + 4*1 =466

用这个方法可以将十进制转化为任意进制。

十进制转任意进制的方法一般有两种:

  1.试减法    2.短除法  

总的来说,方法1适合笔算,方法2适合计算机算。试减法就是通过估算反复减去不大于目标数字的权重的n次方来得到每一位的数字,事实上试探的过程。短除法通过反复短除目标数求余来得到每一位上的数字:

比如 1234 转 5 进制  1234 / 5 = 246余 4  246 / 5 = 49 余 1  49 / 5 = 9 余 4  9 / 5 = 1 余 4  1 / 5 = 0 余 1  可以看出,所有的余数就构成了转化的结果 14414。  

通常的A 进制转 B 进制的做法是先将 A 进制转换为十进制,再将十进制的数字转化为B进制。

而对于大数的进制转换,则不能直接短除,我们改为按位除,但整个过程仍然是短除法的思想。比如将1001由十进制转化为二进制,第一轮从最高位1开始,1/2商0余1,计算0时,不是直接用0来除以2,而是由上一位的余数*基数10+此位数,即被除数为1*10+0=10,10/2商5余0,以此类推,得到商为0500,即500,最后一位的余数为1,第一轮完成,余数1即为转化后结果的最低位,由500开始下一轮,直到被除数为0。事实上,每一轮都是大数除法的过程,也就是模拟了手动计算除法的过程。

2.位运算总结

在计算机程序中,数据的位是可以操作的最小数据单位,理论上可以用“位运算”来完成所有的运算和操作。一般的位操作是用来控制硬件的,或者做数据变换使用,但是,灵活的位操作可以有效地提高程序运行的效率。C语言提供了位运算的功能, 这使得C语言也能像汇编语言一样用来编写系统程序。

C语言提供了六种位运算符:

  & 按位与    | 按位或    ^ 按位异或    ~ 取反    << 左移     >> 右移  

1. 按位与运算 按位与运算符"&"是双目运算符。其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位均为1时,结果位才为1 ,否则为0。参与运算的数以补码方式出现。

    例如:9&5可写算式如下: 00001001 (9的二进制补码)&00000101 (5的二进制补码)    00000001 (1的二进制补码)可见9&5=1。    应用:    a. 清零特定位 (mask中特定位置0,其它位为1,s=s&mask)(mash是掩码)    b. 取某数中指定位 (mask中特定位置1,其它位为0,s=s&mask)  

2. 按位或运算 按位或运算符“|”是双目运算符。其功能是参与运算的两数各对应的二进位相或。只要对应的二个二进位有一个为1时,结果位就为1。参与运算的两个数均以补码出现。

  例如:9|5可写算式如下:    00001001|00000101    00001101 (十进制为13)可见9|5=13    应用:    常用来将源操作数某些位置1,其它位不变。 (mask中特定位置1,其它位为0 s=s|mask)  

3. 按位异或运算 按位异或运算符“^”是双目运算符。其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。参与运算数仍以补码出现。

    例如9^5可写成算式如下:    00001001^00000101 00001100 (十进制为12)    应用:    a. 使特定位的值取反 (mask中特定位置1,其它位为0 s=s^mask)    b. 不引入第三变量,交换两个变量的值 (设 a=a1,b=b1)    目 标         操 作    操作后状态    a=a1^b1     a=a^b    a=a1^b1,b=b1    b=a1^b1^b1  b=a^b    a=a1^b1,b=a1    a=b1^a1^a1  a=a^b    a=b1,b=a1  

4. 求反运算 求反运算符~为单目运算符,具有右结合性。 其功能是对参与运算的数的各二进位按位求反。

    例如~9的运算为: ~(0000000000001001)结果为:1111111111110110  

5. 左移运算 左移运算符“<<”是双目运算符。其功能把“<< ”左边的运算数的各二进位全部左移若干位,由“<<”右边的数指定移动的位数, 高位丢弃,低位补0。 其值相当于乘2。

    例如: a<<4 指把a的各二进位向左移动4位。如a=00000011(十进制3),左移4位后为00110000(十进制48)。  

6. 右移运算 右移运算符“>>”是双目运算符。其功能是把“>> ”左边的运算数的各二进位全部右移若干位,“>>”右边的数指定移动的位数。其值相当于除2。


●例题分析

在这里列举位运算的常见应用:

(1) 判断奇偶:a&1 = 0 偶数,a&1 = 1 奇数。

(2) 取int型变量a的第k位 (k=0,1,2……sizeof(int)),即a>>k&1

(3) 将int型变量a的第k位清0,即a=a&~(1 <<k)

(4) 将int型变量a的第k位置1, 即a=a |(1 <<k)

(5) int型变量循环左移k次,即a=a < <k |a>>16-k (设sizeof(int)=16)

(6) int型变量a循环右移k次,即a=a>>k |a < <16-k (设sizeof(int)=16)

(7)整数的平均值

对于两个整数x,y,如果用 (x+y)/2 求平均值,会产生溢出,因为 x+y 可能会大于INT_MAX,但是我们知道它们的平均值是肯定不会溢出的,我们用如下算法:

int average(int x, int y) //返回X,Y 的平均值  {       return (x&y)+((x^y)>>1);  }  

(8)判断一个整数是不是2的幂:

boolean power2(int x)  {      return ((x&(x-1))==0)&&(x!=0);  }  

(9)不用temp交换两个整数

void swap(int x , int y)  {      x ^= y;      y ^= x;      x ^= y;  }  

(10)计算绝对值

int abs( int x )  {     int y ;     y = x >> 31 ;     return (x^y)-y ; //or: (x+y)^y  }  

(11)取模运算转化成位运算 (在不产生溢出的情况下): a % (2^n) 等价于 a & (2^n - 1)

(12)乘法运算转化成位运算 (在不产生溢出的情况下):a * (2^n) 等价于 a << n

(13)除法运算转化成位运算 (在不产生溢出的情况下):a / (2^n) 等价于 a>> n

(14) a % 2 等价于 a & 1

(15) if (x == a) x= b; else x= a;等价于 x= a ^ b ^ x;

(16) x 的 相反数 表示为 (~x+1)

位运算在题目中经常用到,例如利用二进制枚举的题目,状态压缩DP等用到了位运算。


1.5 中国剩余定理
●知识精讲

这个问题源自于我国数学古书《孙子算经》中的一道问题:“今有物,不知其数,三三数之,剩二;五五数之,剩三;七七数之,剩二。问物几何?”意思是一个整数除以三余二,除以五余三,除以七余二,求这个整数(满足条件且最小)。

做法是:

 n%3=2,n%5=3,n%7=2且3,5,7互质   找到使(5×7)的倍数模3得1的数,答案是70   找到使(3×7)的倍数模5得1的数,答案是21   找到使(3×5)的倍数模7得1的数,答案是15   那么(70×2+21×3+15×2) % (3×5×7) = 23,23就是最终答案了  

理解如下:

70×2 = 140,当中的2是指n%3 = 2的2,因为70%3=1,乘2后使其能满足%3=2的条件,同理,  21×3使其能满足%5=3  15×2使其能满足%7=2  又70能整除5和7,21能整除3和7,15能整除3和5  因此70×2+21×3+15×2 = 233能满足%3=2,%5=3,%7=2的条件  将233对3×5×7=105取模,是为了取得最小的情况,因为105是能够同时整除3,5,7的数,如果减去,对该数满足%3=2,%5=3,%7=2没有影响。因此对105取模,得到的结果便是最小并满足条件的数  

拓展开来问题就是有同余方程组 a = ai (mod ni), 求未知数a。 方法是:

定义 n=n1*n2...nk, 其中因子两两互质  mi = n1*n2*...nk / ni;     ci = mi(mf  mod ni);     其中 mi*mf  mod ni = 1;  则 a = (a1*c1+a2*c2+...+ak*ck) (mod n)   

中国剩余定理关键是mf的求法,如果理解了扩展欧几里得 ax+by=d, 就可以想到:

          mi*mf  mod ni = 1 => mi*mf+ni*y=1;  

这里的中国剩余定理必须要求除数是互质的,但是有些题目的同余方程式除数并不互质,那么将不能使用传统的中国剩余定理


●例题分析

问题描述:POJ 1006

人自出生起就有体力,情感和智力三个生理周期,分别为23,28和33天。一个周期内有一天为峰值,在这一天,人在对应的方面(体力,情感或智力)表现最好。通常这三个周期的峰值不会是同一天。现在给出三个日期,分别对应于体力,情感,智力出现峰值的日期。然后再给出一个起始日期,要求从这一天开始,算出最少再过多少天后三个峰值同时出现。

问题分析:

这一题的做法可以类比算经中问题的方法

找到使(23×28)的公倍数模33得1的数,答案是1288

找到使(23×33)的公倍数模28得1的数,答案是14421|

找到使(28×33)的公倍数模23得1的数,答案是5544

(5544×p+14421×e+1288×i) % (23×28×33) = ans + d

若使用中国剩余定理的一般情况下的处理,则可按照一般情况的方法写出程序,参考核心程序为:

     int mod[3],res[3];//除数,余数  
     void exGCD(int a,int b,int &x,int &y)//扩展欧几里得   
     {     
           if (b==0)
           {        
               x = 1;
               y = 0;
               return;     
            }     
            exGCD(b,a%b,x,y);     
            int temp = x;     
            x = y;     
            y = temp-a/b*y;  
    }    
     int china_mod()//中国剩余定理   
     {      
          int mul=1,ans=0,mf,y,mi;      
          for (int i=0; i<3; i++)         
              mul *= mod[i];      
          for (int i=0; i<3; i++)
          {       
               mi = mul/mod[i];       
               exGCD(mi,mod[i],mf,y);      
               ans += (mi*mf*res[i])%mul;      
           }      
          return (ans+mul)%mul;  
     }


一、综合实战—使用极轴追踪方式绘制信号灯 实战目标:利用对象捕捉追踪和极轴追踪功能创建信号灯图形 技术要点:结合两种追踪方式实现精确绘图,适用于工程制图中需要精确定位的场景 1. 切换至AutoCAD 操作步骤: 启动AutoCAD 2016软件 打开随书光盘中的素材文件 确认工作空间为"草图与注释"模式 2. 绘图设置 1)草图设置对话框 打开方式:通过"工具→绘图设置"菜单命令 功能定位:该对话框包含捕捉、追踪等核心绘图辅助功能设置 2)对象捕捉设置 关键配置: 启用对象捕捉(F3快捷键) 启用对象捕捉追踪(F11快捷键) 勾选端点、中心、圆心、象限点等常用捕捉模式 追踪原理:命令执行时悬停光标可显示追踪矢量,再次悬停可停止追踪 3)极轴追踪设置 参数设置: 启用极轴追踪功能 设置角度增量为45度 确认后退出对话框 3. 绘制信号灯 1)绘制圆形 执行命令:"绘图→圆→圆心、半径"命令 绘制过程: 使用对象捕捉追踪定位矩形中心作为圆心 输入半径值30并按Enter确认 通过象限点捕捉确保圆形位置准确 2)绘制直线 操作要点: 选择"绘图→直线"命令 捕捉矩形上边中点作为起点 捕捉圆的上象限点作为终点 按Enter结束当前直线命令 重复技巧: 按Enter可重复最近使用的直线命令 通过圆心捕捉和极轴追踪绘制放射状直线 最终形成完整的信号灯指示图案 3)完成绘制 验证要点: 检查所有直线是否准确连接圆心和象限点 确认极轴追踪的45度增量是否体现 保存绘图文件(快捷键Ctrl+S)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值