• [置顶] 数学的坑,一点点来填


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

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

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

       同余方程:

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

        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;
    		}
    	}
    }

      总结就告一段落了。。

  • 相关阅读:
    RxJS 系列 – Error Handling Operators
    RxJS 系列 – Join Creation Operators
    Google – Reviews
    Google Analytics – GA4 & Tag Manager 概念篇
    DOM & BOM – Input File, Drag & Drop File, File Reader, Blob, ArrayBuffer, File, UTF8 Encode/Decode, Download File
    RxJS 系列 – 大杂烩
    RxJS 系列 – Join Operators
    RxJS 系列 – 实战练习
    前端接收文件流并下载解决乱码问题
    package.json 与 packagelock.json 的关系
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7632722.html
Copyright © 2020-2023  润新知