数论模板

1.exgcd

#define ll long long

void exgcd(ll a,ll b)
{
    if(b==0)
    {
        x=1,y=0;gcd=a;
        return;
    }exgcd(b,a%b);
    ll tmp=x,x=y,y=tmp-a/b*y;
}
View Code

 2.素数

#define N 1000007

void prime()
{
    for(int i=2;i<=N;i++)
    {
        if(!no[i]) prime[++tot]=i;
        for(int j=1;j<=tot;j++)
        {
            if(i*prime[j]>=N)break;
            no[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
    }
}
欧拉筛
#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>

#define ll long long
#define N 100010

using namespace std;
ll p,a;

ll kfc(ll a,ll b)
{
    ll res=0;
    a%=p;b%=p;
    while(b)
    {
        if(b&1) b--,res+=a,res%=p;
        a<<=1,a%=p,b>>=1;
    }return res%p;
}

ll ksm(ll a,ll b)
{
    ll res=1;
    while(b)
    {
        if(b&1) res=kfc(res,a)%p;
        b>>=1; a=kfc(a,a)%p;
    }return res;
}

int main()
{
    srand(time(0));
    cin>>p;
    for(ll i=1;i<=15;i++)
    {
        a=rand()%(p-1)+1;
        ll x=ksm(a,p-1);
        if(x!=1)
        {
            printf("NO\n");
            return 0;
        }
    }
    printf("Yes\n");
    return 0;
}
费马小定理判素数(快速幂 快速乘)

 3.质因数分解

3.

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int n;
int a[10000];

int main()
{
    scanf("%d",&n);
    printf("%d=",n);
    int cnt=0;
    for (int i=2;i<=n;i++)
    {
        while (n%i==0&&n)
        {
            a[cnt++]=i;
            n/=i;
        }
    }
    for (int i=0;i<cnt-1;i++)
    {
        printf("%d*",a[i]);
    }
    printf("%d\n",a[cnt-1]);
    return 0;
} 

分解单个数
单个数
#include<iostream>
#include<cstdio>
#include<cstring>

#define N 100010

using namespace std;
int no[N],prime[N],cnt[N];
int tot,n;

void is_prime()
{
    for(int i=2;i<=N;i++)
    {
        if(!no[i]) prime[++tot]=i;
        for(int j=1;j<=tot;j++)
        {
            if(i*prime[j]>=N) break;
            no[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
    }
}

int main()
{
    is_prime();int x=1;
    scanf("%d",&n);tot=0;
    for(int i=1;i<=n;i++)
    {
        x=1;
        tot++;int P=prime[i];
        while(x)
        {
            x=n/P;
            cnt[tot]+=x;
            P*=prime[i];
        }
    }
    for(int i=1;i<=tot;i++) if(cnt[i]!=0)printf("%d ",cnt[i]);
    return 0;
}
阶乘

4.卡特兰数

1.f(n)=f(n-1)*(4*n-2)/(n+1)

2.h(0)=0,h(1)=1

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

#include <iostream>
#include <stdio.h>
#include <cmath>
using namespace std;

int a[105][105];    //
int b[105];       

void catalan()  
{
    int i,j,len,carry,temp;
    a[1][0]=b[1]=1;
    len=1;
    for(i=2;i<=100;i++)
    {
        for(j=0;j<len;j++)   
            a[i][j]=a[i-1][j]*(4*(i-1)+2);
        carry=0;
        for(j=0;j<len;j++)    
        {
            temp=a[i][j]+carry;
            a[i][j]=temp%10;
            carry=temp/10;
        }
        while(carry)    
        {
            a[i][len++]=carry%10;
            carry/=10;
        }
        carry=0;
        for(j=len-1;j>=0;j--) 
        {
            temp=carry*10+a[i][j];
            a[i][j]=temp/(i+1);
            carry=temp%(i+1);
        }
        while(!a[i][len-1])    
            len--;
        b[i]=len;
    }
}

int main()
{
    int i,n;
    catalan();
    scanf("%d",&n);
    for(i=b[n]-1;i>=0;i--)
      printf("%d",a[n][i]);
    return 0;
}
高精度

5.逆元

/*
P3811
*/
#include<bits/stdc++.h>

#define N 3000007
#define ll long long

using namespace std;
ll n,m,p;
ll inv[N];

inline ll read()
{
    ll x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

int main()
{
    n=read();p=read();inv[1]=1; 
    for(int i=2;i<=n;i++)
    {
        inv[i]=(p-p/i)*inv[p%i]%p;
    }
    for(int i=1;i<=n;i++) printf("%lld\n",inv[i]);
    return 0;
}
线性求逆元

 6.欧拉函数

int get_phi(int x)
{
    int ret=1;
    for(int i=1;prime[i]*prime[i]<=x;i++)
    {
        if(x%prime[i]==0)
        {
            ret*=prime[i]-1;x/=prime[i];
            while(x%prime[i]==0) x/=prime[i],ret*=prime[i];
        }
    }
    if(x>1) ret*=x-1;
    return ret;
}
beautiful!
void get_phi()
{
    cnt = 0;
    memset(is_prime, true, sizeof(is_prime));
    phi[1] = 1;
    for(int i=2; i<N; i++)
    {
        if(is_prime[i])///素数
        {
            p[cnt++] = i;
            phi[i] = i-1;///素数的欧拉函数值是素数- 1
        }
        for(int j=0; j<cnt; j++)
        {
            if(i*p[j] > N) break;
            is_prime[i*p[j]] = false;///素数的倍数,所以i*p[j]不是素数
            if(i%p[j] == 0)///性质:i mod p == 0, 那么 phi(i * p) == p * phi(i)
            {
                phi[i*p[j]] = p[j] * phi[i];
                break;
            }
            else phi[i*p[j]] = (p[j]-1) * phi[i];///i mod p != 0, 那么 phi(i * p) == phi(i) * (p-1) 
        }
    }
}
线筛欧拉函数

 

 7.高斯消元

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
int n;
double f[101][101],ans[101];
const double eps=1e-12;

int dcmp(double x)
{
    if(x<=eps && x>=-eps) return 0;
    return (x>0)?1:-1;
}

bool gauss()
{
    for(int i=1;i<=n;i++)
    {
        int num=i;
        for(int j=i+1;j<=n;j++)
          if(dcmp(f[i][j]-f[num][i])>0)
            num=j;
        if(num!=i)
          for(int j=1;j<=n+1;j++)
            swap(f[i][j],f[num][j]);
        for(int j=i+1;j<=n;j++)
          if(dcmp(f[j][i]))
          {
                double t=f[j][i]/f[i][i];
                for(int k=1;k<=n+1;k++)
                  f[j][k]-=t*f[i][k];
          }
    }
    
    for(int i=n;i>=1;i--)
    {
        if(dcmp(f[i][i])==0) return 0;
        for(int j=i+1;j<=n;j++) f[i][n+1]-=f[i][j]*ans[j];
        ans[i]=f[i][n+1]/f[i][i];
    }return 1;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n+1;j++)
        scanf("%lf",&f[i][j]);
        
    if(gauss())
      for(int i=1;i<=n;i++)
        printf("%.2lf\n",ans[i]);
    else puts("No Solution\n");
    return 0;
}
P3389

 8.中国剩余定理

void exgcd(int a,int b)
{
    if(b==0)
    {
        x=1;y=0;
        return;
    }
    exgcd(b,a%b);
    int tmp=x;x=y;y=tmp-(a/b)*y;
}

int CRT(int a[],int m[],int n)
{
    int M=1,ans=0;
    for(int i=1;i<=n;i++) M*=m[i];
    for(int i=1;i<=n;i++)
    {
        int Mi=M/m[i];
        exgcd(Mi,m[i]);
        ans=(ans+Mi*x*a[i])%M;
    }
    if(ans<0) ans+=M;
    return ans;
}
CRT

 9.组合数

inline void combination()
{
    for(int i=0;i<=n;i++)  
        for(int j=0;j<=i;j++)  
            if(!j || i==j)  c[i][j]=1;  
            else  c[i][j]=c[i-1][j-1]+c[i-1][j];  
    c[0][0]=0;  
    return;  
}
递推

 10.Lucas定理

int ksm(int a,int b,int p)
{
    int res=1;
    while(b)
    {
        if(b&1) res=res*a%p;
        b>>=1;a=a*a%p;
    }return res;
}

int C(int n,int m,int p)
{
    if(m>n)return 0;
    return  fac[n]*ksm(fac[m]*fac[n-m],p-2,p)%p;
}

int Lus(int n,int m,int p)
{
    if(m==0) return 1;
    return (C(n%p,m%p,p)*Lus(n/p,m/p,p))%p;
}
~

 

posted @ 2017-09-01 16:19  安月冷  阅读(172)  评论(0编辑  收藏  举报