zoukankan      html  css  js  c++  java
  • 欧拉函数板子

    线性素数筛

    • 1 不管i是不是素数,它与素数的乘积一定不是素数,直接use =1;

    • 如果use=0那么i是素数加入到ss表中,然后枚举素数表,执行操作1,如果i是合数,如果素数表中有它的质因数,则说明已经被质因数筛过了,直接break即可。

    void pd()
    {
        use[1]=1;
        for(int i=2;i<=n;i++)
        {
            if(use[i]==0);
                a[++k]=i;
            for(int j=1;j<=k&&i*a[j]<=n;j++)
            {
                use[i*a[j]]=1;
                if(i%a[j]==0)
                    break; 
            }
        }
        return ;
    }
    

    线性求欧拉函数

    什么是欧拉函数,欧拉定理

    欧拉函数性质:

    • 因为欧拉函数是积性函数雾,如果i与p互质则有 ph (i*p) =ph i *ph p (i%p!=0)

    • ph i*p=ph i* p (i%p==0)不论p是不是质数

    这样就可以枚举出所有情况下的欧拉函数

    边线性筛边算欧拉函数:

    void get_phi()
    {
        for(int i=1;i<=N-3;i++)
            phi[i]=i;
        use[1]=1;
        for(int i=2;i<=N-3;i++)
        {
            if(use[i]==0)
            {
                ss[++k]=i;
                phi[i]=i-1;
            }
            for(int j=1;j<=k&&i*ss[j]<=N-3;j++)
            {
                int temp=i*ss[j];
                use[temp]=1;
                if(i%ss[j]==0)//i是ss的倍数 
                {
                    phi[temp]=phi[i]*ss[j];
                    break;
                }
                else
                {
                    phi[temp]=phi[i]*(ss[j]-1);
                }
            }    
        }
    }
    

    求单个的欧拉函数

    inline long long phi(long long x) 
    {
        long long s=x,i=2;
        for (;i*i<=x;i++) if (!(x%i)) {s=s/i*(i-1); for (;!(x%i);x/=i);}
        if (x>1) s=s/x*(x-1); return s;
    }
    

    乘法逆元

    其实乘法逆元就相当于除法a变为乘a分之一基础模板题目这里
    贴代码吧

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cstdlib>
    using namespace std;
    const int N=3e6+6;
    long long n,p,inv[N]; 
    int main()
    {
    	scanf("%lld %lld",&n,&p);
    	inv[1]=1;
    	inv[0]=0;
    	for(int i=2;i<=n;i++)
    	{
    		inv[i]=(p-(p/i)*inv[p%i]%p)%p;
    	}
    	for(int i=1;i<=n;i++)
    		printf("%lld
    ",inv[i]);
    	return 0;
    }
    

    下面是对逆元的证明:

    [p=k*i+r;这里的p是mod,iin [2,n]\ k=p/i; quad r=p\%i\ k*i+r=0 quad mod p\ k*inv[r]+inv[i]=0quad mod p\ 等式两边同时乘上i,r的逆元\ p/i*inv[p\%i]+inv[i]=0 quad 为避免出现负数所以加一个p\ inv[i]=(p-p/i*inv[p\%i]\%p)\%p \ ]

    还有一种求逆元的方法
    如果mod是质数的话则
    a-1 =a(p-2) mod p 而这个可以用快速幂优化

    不会的请转这里
    卡常题目这里

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<cstdlib>
    #include<vector>
    using namespace std;
    const int N=5e6+6; 
    long long maxn,n,p,temp=1,s[N],k,sinv,sum,a[N],inv[N];
    long long read()
    {
    	int ans=0,w=1;char ch=getchar();
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-')
    			w=-1;//注意这里一定不能写成了 ,
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		ans=(ans<<1)+(ans<<3)+ch-'0';
    		ch=getchar();
    	}
    	return ans*w;
    }
    long long pow3(long long a,long long b)
    {
    	long long ans=1;
    	a=a%p;
    	while(b)
    	{
    		if(b&1)
    			ans=ans*a%p;
    		a=a*a%p;
    		b=b>>1;
    	}
    	return ans%p;
    }
    int main()
    {
    	//freopen("niyuan.in","r",stdin);
    	//freopen("niyuan.out","w",stdout);
    	n=read();p=read();k=read();
    	s[0]=1;
    	for(int i=1;i<=n;i++)
    	{
    		a[i]=read();
    		s[i]=s[i-1]*a[i]%p;
    	}
    	sinv=pow3(s[n],p-2)%p;
    	for(int i=n;i>=1;i--)
    	{
    		inv[i]=sinv*s[i-1]%p;
    		sinv=sinv*a[i]%p;
    	}
    	for(int i=1;i<=n;i++)
    	{
    		temp=temp*k%p;
    		sum=(sum+temp*inv[i]%p)%p;		
    	}
    	printf("%lld
    ",sum%p);
    	return 0;
    }
    
    

    gcd和exgcd

    顺便贴一下exgcd吧(gcd可以用__gcd(a,b)这个自带函数)

    扩欧是求符合 ax+by=c的最小整数解顺便求出gcd(a,b)

    函数的参数a, b即为等式当中的两个参数,x和y传引用,可以从过程当中求出x和y,返回值是gcd(a, b)。

    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    long long extend_gcd(long long a, long long b, long long &x, long long &y)
    {
        if(b == 0)
        {
            x = 1, y = 0;
            return a;
        }
        else
        {
            long long r = extend_gcd(b, a%b, y, x);
            y -= x*(a/b);
            return r;
        }
    }
    
  • 相关阅读:
    vs里替换的正则表达式引用
    javascript学习
    filter用法(使静态页面和js通过iis的asp.net过滤器)
    表格的交替选择行【jquery中siblings的用法】
    表格的cell固定宽度,当内容达到宽度时换行
    collection模块(具名元组、队列、有序字典、默认值字典)、time 模块、随机模块:random、os模块、sys模块、序列化模块
    继承的用法、属性的查找顺序、组合、新式类与经典类、菱形继承等
    多态、以及常用的关于类的方法(isinstance、issubclass、slots等)运算符重载的实现、上下文管理等
    封装、prorerty装饰器、python实现封装的原理等
    面向对象、类和对象、__dict__方法、__init__方法、对象绑定方法、类绑定方法、对象交互
  • 原文地址:https://www.cnblogs.com/cherrypill/p/13929060.html
Copyright © 2011-2022 走看看