您的位置:首页 > 其它

[未完待续][笔记]数论相关---基础

2017-10-06 09:13 211 查看
证明是什么,本蒟蒻不懂

代码统一放在最后

一.排列与组合

 PS: 1.简单规定: 0!=1 2.收集资料仅供参考,多半摘自百度

  1.排列

   —定义:从n个不同元素中取出m(m≤n)个元素的所有排列的个数,叫做从n个不同元素中取出m个元素的排列数,用符号 A(n,m)表示(或P(n,m))[与顺序有关]

   —计算公式:




  2.组合

   —定义:从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数。用符号 C(n,m) 表示 [与顺序无关]

   —计算公式:


   —性质:


   —递推公式:C(m,n)=C(m-1,n-1)+C(m-1,n)

   —边界条件:当 m==n || n==0 时 C(m,n)==1

    不存在 n>m

  补:关于”n个球放入m个盒子m”的问题,可参考该博客

  若是高精度,要么递推加法,要么分解质因数解决除法问题(不会有人码除法吧。。)

 

  3.二项式定理杨辉三角

  
4000
  —二项式定理:


    —杨辉三角:略...

    —关系(看看前面的组合数递推公式和性质,有什么发现~):二项式定理的系数C(n,i)与杨辉三角一致

   —某些性质:二项式展开式中所有系数总和是2^n—每行杨辉三角的和为2^n

   ( C(n,0)+C(n,1)+C(n,2)+…+C(n,n)==2^n )

  

二.某些数列(感觉普遍打表找规律就行了)

  1.斐波那契数列(Fibonacci)

   —数列:0、1、1、2、3、5、8、13、21、34...

   (从第0项开始,下同)

   —表达式:F
=F[n-1]+F[n-2] (n>=2,F[0]=0,F[1]=1)

   —计算优化:矩阵乘法

   —相关性质:

     *将杨辉三角左对齐,将同一斜行的数加起来,即可得到数列

     —>f(n)=C(n-1,0)+C(n-2,1)+…+C(n-1-m,m) (m<=n-1-m)

     *gcd(f
,f[m])=f[gcd(n,m)]


     *尾数循环:

       一位:60

       两位:300

       三位:1500

       …

    2.卡特兰数(Catalan)

     通常来说,多半高精

     —数列:1, 1, 2, 5, 14, 42, 132, 429, 1430...

     —计算公式:

       h(n)= h(0)*h(n-1)+h(1)*h(n-2) + … + h(n-1)*h(0) (n>=2)

       h(n)=h(n-1)*(4*n-2)/(n+1)

       h(n)=C(2n,n)/(n+1)[不用做除法,直接化简分解质因数即可]

       h(n)=c(2n,n)-c(2n,n-1)(n=0,1,2,…)

     —应用:

       括号化

       出栈次序

       凸多边形三角划分

       给定节点组成二叉搜索树

       n对括号正确匹配数目

       …

 三.最大公约数与扩展欧几里德

   1.gcd

     —辗转相除法:gcd(a,b)=gcd(b,a mod b)

            当b==0时 a即为所求

     —辗转相减法:(适用于高精度)

       * a,b均为偶数:gcd(a,b)=gcd(a/2,b/2)

       * a为偶数:gcd(a,b)=gcd(a/2,b)

       * b为偶数:gcd(a,b)=gcd(a,b/2)

       * 其余:gcd(a,b)=gcd(abs(a-b),min(a,b))

       * a==0, 则b为所求 ; b==0,则反之

   2.扩展欧几里德

     定义:找到一组解(x,y)满足 a *x + b *y = gcd(a,b)

     算法:同辗转相除法,只需要多加两个参数x,y并进行一下操作

       –b==0 x=1,b=0

       –b!=0  x=y1, y=x1- a/b*y1

     简单证明:

       已知存在x,y满足 gcd(b,a%b)=b x+(a%b) y

     求x1,y1满足gcd(a,b)=a *x1+b *y1

       由gcd(b,a%b)=gcd(a,b)可知

       b* x+(a%b)* y=a* x1+b*y1

       b* x+( a-[a/b]* b)* y = a* x1+b* y1

       整理得到:

         a* y+b * (x-[a/b] * y)=a* x1+b * y1

       目测得(—-):

         x1=y   y1=x-[a/b] * y

       PS:[ ]表示去尾整除

     应用:求乘法逆元,解不定方程解,解同余方程

     相关:对于ax + by = c,当c为gcd(a,b)倍数时才有解

     

四.同余方程,中国剩余定理与逆元

  1.同余

    定义:定一个正整数m,如果两个整数a和b满足a%m与b%m的余数相同,那么就称整数a与b对模m同余,记作a≡b(mod m)。

    PS: 满足 (a-b)为m的整数倍

    性质:(a+b)%m=((a%m) +(b%m))%m

       (a-b)%m=((a%m) -(b%m))%m

       (a*b)%m=((a%m) *(b%m))%m

       (a^b)%m=((a%m)^b)%m

        若ac=bc(mod m),且gcd(m,c)=d,则a≡b(mod m/d)

    同余方程:形如 ax≡b(mod n)的方程求解x

    根据性质可知: ax-b为n的整数倍,则令ax-b=ny

    移项可得: ax-ny=b { 此时即为不定方程,见扩欧 }

    

    这里详细考虑 ax≡1(mod n)的情况,即b=1{此时,解称为a关于模n的逆,见下文}.则 ax-ny=1 { 此时只有gcd(a,n)=1时才有解 }

  2.中国剩余定理(孙子定理)

    初始问题描述:在《孙子算经》中有这样一个问题:“今有物不知其数,三三数之剩二(除以3余2),五五数之剩三(除以5余3),七七数之剩二(除以7余2),问物几何?” 这不就是道小学奥数题么...

    PS:该问题的一般解法即为"中国剩余定理"

    数学模型:给出a与m,求x

      x≡a1(mod m1)

      x≡a2(mod m2)

      x≡a3(mod m3)

      ……………….

      x≡ak(mod mk)

    只有当m1,m2,…mk两两互质时,该同余方程组有整数解,并且在模M=m1*m2… * mk下解是惟一的

    解为:

      


    其中Mi=M/m,Mi^-1 为Mi模mi的逆元

  3.乘法逆元

    定义:如果ax≡1 (mod m),且gcd(a,m)=1(a与m互质),则称a关于模m的乘法逆元为x。

    其实类似于倒数(在%m的条件下):

      若gcd(b,m)=1,则存在x使得 b*x≡1(mod m)

      则对于 a/b % mo 可做相应简化:

        a/b≡(a/b) * 1≡(a/b) * (b*x)≡a * x( mod m)

    应用:简化在取模下计算除法时的不便(如计算C,可以免去高精)

    方法:b * x≡1 ( mod m)

      扩展欧几里得:b,m互质

      欧拉函数:m不为质数

      费马小定理: m为质数

      线性算法:m为质数

  这些模板有空再补吧。。

       

扩展欧几里德 { ax+by=c }

#include <cstdio>
#include <cstdlib>
#define ll long long
#define open(s) freopen(s".in","r",stdin); freopen(s".out","w",stdout);
#define close fclose(stdin); fclose(stdout);
using namespace std;

inline ll read()
{
int k=1;
ll sum=0;
char c=getchar();
for(;'0'>c || c>'9' ;c=getchar())
if(c=='-') k=-1;
for(;'0'<=c && c<='9';c=getchar())
sum=sum*10+c-'0';
return sum*k;
}

inline void write(ll x)
{
if(x<0) { putchar('-'); x*=-1; }
if(x>9) write(x/10);
putchar(x%10+'0');
}

inline ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b)
{
x=1; y=0;
return a;
}
ll d,tmp;
d=exgcd(b,a%b,x,y);

tmp=x-(a/b)*y;
x=y;
y=tmp;

return d;
}

int main()
{
ll a,b,c,d,x,y;
x=y=0;
a=read(); b=read(); c=read();
if(a<0) { a=-a; c=-c; }
d=exgcd(a,b,x,y);
if(c%d==0)
{
a/=d; b/=d; c/=d;
write(((c*x)%b+b)%b);
}else
printf("Impossible");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: