数学的坑,一点点来填

来源:互联网 发布:mac后台怎么关闭 编辑:程序博客网 时间:2024/05/13 02:29

   数学这个坑实在太大了,说白了是我太弱了 

   联赛考的:同余(解方程+逆元),欧拉函数,筛素数(这个过了),组合数,矩阵乘+快速幂,高斯消元

   一点点把板子都总结一下。

   同余方程:

   首先是解线性同余的板子。

    p*a+q*b=gcd(a,b)=gcd(b,a%b)=p*b+q*a%b=p*b+q*(a-a/b*b)=q*a+(p-a/b*q)*b;

    根据这个式子得到。。

    

int exgcd(int a,int b,int &x,int &y){if(!b){x=1;y=0;return a;}int c=exgcd(b,a%b,x,y);int tmp=x;x=y;y=tmp-a/b*y;return c;}
    求逆元

    概率题经常用到。

    这里提两种算法。

    1.求单值的。

ll ny(int a,int b,int c){    if(!a)return -1;    else if(!(c%a))return c/a;    ll t=ny(b%a,a,((-c%a)+a)%a);    if(t==-1)return -1;    return (t*b+c)/a;}ll hh=ny(x,y,1);
    2.线性找

    假设  k*i+r    %p==0

    两边同乘  i^-1   r^-1,   k*r^-1+i^-1   %p==0

                                       i^-1 %p  ==-k*r^-1

                                      i^-1%p==-(p/i)*(p%i)^-1(我不太会证)

    于是可以递推求了

A[i]=-(p/i)*A[p%i];

   3. ny(i)=i^(mod-2);


   中国剩余定理暂过。。

    高斯消元:

    概率题常用到,就是个板子,但记得不太准。。

     num为了处理无解,如果一定有解,num可替成i。

void gaosi(){/*已知a[i][j]是第i个方程,第几个变量的参数,  b[i]是第i个方程的常量 */int im,num=1;for(int i=1;i<=n;i++,num++){im=i;for(int j=i+1;j<=n;j++)    if(fabs(a[j][i])>fabs(a[im][i]))         im=j;if(im!=i){for(int j=1;j<=n;j++)    swap(a[i][j],a[im][j]);swap(b[i],b[im]);}if(!a[num][i]){num--;continue;}for(int j=num+1;j<=n;j++){if(!a[num][j])continue;double t=a[j][i]/a[num][i];for(int k=i+1;k<=n;k++)     a[j][k]-=a[i][k]*t;b[j]-=b[i]*t;}}for(int i=n;i>=1;i--){for(int j=n;j>i;j--)    b[i]-=a[i][j]*ans[j];ans[i]=b[i]/a[i][i];}}

   组合数:

    首先说一下线性求法,应付大量询问,打个表。

    

void init(){for(int i=1;i<=2000;i++)   for(int j=1;j<=i;j++)       if(i==1&&(j==1||j==i))          c[i][j]=1;        else          c[i][j]=c[i-1][j]+c[i-1][j-1];}
    然后就是大组合数取模,卢卡斯定理。

    

int get(int n,int m){if(n<m)return 0;if(m>n-m)m=n-m;int s1=1,s2=1;for(int i=0;i<m;i++){s1=s1*(n-i)%mod;s2=s2*(i+1)%mod;}return (s1*cheng(s2,mod-2))%mod;//cheng()指快速幂 }int lucas(int n,int m){if(m==0)return 1;return get(n%mod,m%mod)%mod*lucas(n/mod,m/mod)%mod;}

3.也可以预处理阶乘,逆元(逆元太大递归求)。    

卡特兰数

  不知道会不会考,而且我只会求单个值,Catalan(n)=C(2n,n)-C(2n,n-1);

欧拉函数:

      1.线性求。

       同时能把素数筛出来。

       对于素数,phi(i)=i-1;

       对于非素数,(i%p!=0)   phi(i*p)=phi(i)*phi(p);

                             (i%p==0)  phi(i*p)=phi(i)*p;

      

void get_phi(){phi[1]=1;for(int i=2;i<=N;i++){if(!mark[i])//是不是素数 {prime[++tot]=i;phi[i]=i-1;}for(int j=1;j<=tot;j++){if(i*prime[j]>N)break;mark[i*prime[j]]=1;if(!(i%prime[j]))            {            phi[i*prime[j]]=phi[i]*prime[j];            break;}else    phi[i*prime[j]]=phi[i]*phi[j];//利用欧拉函数积性   }}} 

     2,求单个值的

int get_phi(int t){int k=t;for(int i=2;i*i<=t;i++)    if(t%i==0)    {    k=k-k/i;    while(t%i==0)         t/=i;}if(t>1)k=k-k/t;return k;}

      

矩阵乘+快速幂

    矩阵乘没啥好说的。。

node cheng(node a,node b){node c;for(int i=1;i<=n;i++)   for(int j=1;j<=n;j++)      for(int k=1;k<=n;k++)  c[i][j]+=a[i][k]*b[i][k];return c;}
    快速幂
int quick(int x,int n){int ans=1;while(n){if(n&1)ans*=x;x*=x;}return ans;}
     线性筛素数

   算了,把它也添上吧。。

   

int get_prime(){for(int i=2;i<N;i++){if(!mark[i])prime[++tot]=i;for(int j=1;j<=tot&&i*prime[j]<N;j++){mark[i*prime[j]]=1;if(!(i%prime[j]))break;}}}

  总结就告一段落了。。

原创粉丝点击