Number Theory Template

来源:互联网 发布:有限电视和网络融合 编辑:程序博客网 时间:2024/04/29 02:55
#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <map>#include <vector>//注意题目数据范围,能用int用int,LL有时会超时#define LL long longusing namespace std;//线性素数筛法const long N = 200000;long prime[N] = {0},num_prime = 0;int isNotPrime[N] = {1, 1};void produce_prime(){    for(long i = 2 ; i < N ; i ++)    {if(! isNotPrime[i]) prime[num_prime ++]=i;for(long j = 0 ; j < num_prime && i * prime[j] <  N ; j ++)        {                        isNotPrime[i * prime[j]] = 1;  if( !(i % prime[j] ) )break;}}}//返回gcd(a,b)LL gcd(LL a,LL b){return b==0 ? a:gcd(b,a%b);}//拓展gcd,求解ax+by=d,d=gcd(a,b),且|x|+|y|最小void extend_gcd(LL a,LL b,LL &d,LL &x,LL &y){    if(!b){d=a;x=1;y=0;}else{extend_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//返回ab mod nLL mul_mod(LL a,LL b,LL c){    LL ret=0,tmp=a%c;    while(b)    {        if(b&0x1)if((ret+=tmp)>=c)ret-=c;        if((tmp<<=1)>=c)tmp-=c;        b>>=1;    }    return ret;}//快速幂LL pow_mod(LL a,LL p,LL n){LL ans;    if(p==0)return 1%n;    ans=pow_mod(a,p/2,n);    ans=mul_mod(ans, ans, n);    if(p%2==1)ans=mul_mod(ans, a, n);    return ans%n;}//求单个数的欧拉函数值LL euler_phi(LL n){    LL m, ans;m=(int)sqrt(n+0.5); //////////强烈建议修改,有精度问题ans = n;    for(int i=2;i<=m;i++)        if(n%i==0){            ans=ans/i*(i-1);            while (n%i==0)n/=i;        }    if(n>1)  ans=ans/n*(n-1);    return ans;}//求多个数的欧拉函数值LL phi[N];void phi_table(LL n){    for(int i=2;i<=n;i++)phi[i]=0;    phi[1]=1;    for(int i=2;i<=n;i++){        if(!phi[i]){            for(int j=i;j<=n;j+=i){                if(!phi[j])phi[j]=j;                phi[j]=phi[j]/i*(i-1);            }        }    }}//求逆元LL inv(LL a,LL n){    LL d,x,y;    extend_gcd(a, n, d, x, y);    return d == 1? (x+n)%n:-1;}//求单个线性同余方程ax=b(mod n)LL linear_mod(LL a,LL b,LL n){    LL d, tem;    d=gcd(a,b);    if(b%d==0){        a=a/d;b=b/d;n=n/d;        tem=inv(a, n);        return tem*b%n;    }    return -1;}//CRT,n个方程:x=a[i](mod m[i]) 0<=i<nLL CRT(int n,int *a,int *m){    LL M=1,d,y,x=0;    for(int i=0;i<n;i++)  M*=m[i];    for(int i=0;i<n;i++){        LL w=M/m[i];        extend_gcd(m[i],w,d,d,y);        x=(x+y*w*a[i])%M;    }    return (x+M)%M;}//可以不互素的一次同余方程组求解LL extend_crt(int n,int *a,int *m){    LL a1,m1,a2,m2;    LL flag=0;    LL d,tem,K;    a1=a[0];m1=m[0];    for(int i=1;i<n;i++){        a2=a[i-1];m2=m[i-1];        d=gcd(m1,m2);        if((a2-a1)%d==0){            tem=inv(m1/d, m2/d);            K=(tem*(a2-a1)/d)%(m2/d);            a1=(K*m1+a1)%(m1*m2/d);            m1=m1*m2/d;        }else{            flag=1;        }        if(flag==1)return -1;    }    return (a1+m1)%m1;//注意返回值是0的情况,这时候根据题目要判断是否加m1}//离散对数 baby-step,giant-steapLL log_mod(LL a,LL b,LL n){    LL m,v,e=1,i;map <LL,LL> x;    m=(int)sqrt(n+0.5);    v=inv(pow_mod(a, m, n),n);    x[1]=0;    for(i=1;i<m;i++){        e=mul_mod(e, a, n);        if(!x.count(e))x[e]=i;    }    for(i=0;i<m;i++){        if(x.count(b))return  i*m+x[b];        b=mul_mod(b, v, n);    }    return -1;}//生成较小的组合数#define MAX 101#define MOD 101LL cb[MAX][MAX];//先初始化cb数组都为-1//使用前要估计好大致的范围再对数组大小进行调整LL calc(int n, int k){    if (!k || n == k)return 1;    if (~cb[n][k])return cb[n][k];    return cb[n][k] = (calc(n - 1, k - 1) + calc(n - 1, k)) % MOD;}//第一类stirling数 讲n个元素分为k组,每组中圆排列的组数LL stirling[MAX][MAX];LL calstirling(int n,int k){    if(k>n||(n>0&&k==0))        return 0;    if(n==k)        return 1;    if(~stirling[n][k])        return stirling[n][k];    return stirling[n][k]=(calstirling(n-1,k-1)+(n-1)*calstirling(n-1,k))%MOD;}//分解质因数void factor(int n,int a[MAX],int b[MAX],int &tot){    int temp,i,now;    temp=(int)(sqrt(n)+1);    tot=0;    now=n;    for(i=2;i<=temp;++i)if(now%i==0){        a[++tot]=i;        b[tot]=0;        while(now%i==0){            ++b[tot];            now/=i;        }    }    if(now!=1){        a[++tot]=now;        b[tot]=1;    }}//求原根,返回最小原根vector<LL> a;bool g_test(LL g,LL p){    for(LL i=0;i<a.size();i++)        if(pow_mod(g,(p-1)/a[i],p)==1)            return 0;    return 1;}LL primitive_root(LL p){    LL tmp=p-1;    for(LL i=2;i<=tmp/i;i++)        if(tmp%i==0){            a.push_back(i);            while(tmp%i==0)                tmp/=i;        }    if(tmp!=1){        a.push_back(tmp);    }    LL g=1;    while(true){        if(g_test(g,p))            return g;        ++g;    }}

0 0
原创粉丝点击