11.7数论模板大杂烩

模板测评地

1.简单的素数判断:http://www.codevs.cn/problem/1430/

2.欧拉函数:http://acm.hdu.edu.cn/showproblem.php?pid=1286

3.卡特兰数:http://acm.hdu.edu.cn/showproblem.php?pid=1130

4.斐波那契:https://www.luogu.org/problemnew/show/1962

6.扩展欧几里得:http://acm.hdu.edu.cn/showproblem.php?pid=1576

6.Lucas定理:https://www.luogu.org/problemnew/show/3807

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 10000
#define LL long long
#define mod 1000000007
using namespace std;
int sum,x,y,n,m;
int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='0')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int pd(int n)//简单的素数判定 
{
    for(int i=2;i*i<=n;i++)
     if(n%i==0) return 1;
    return 0;
}
int prime[N];
bool not_prime[N];
int Euler_sieve()//线性筛素数 
{
    not_prime[1]=1;
    for(int i=2;i<=N;i++)
    {
        if(!not_prime[i]) prime[++sum]=i;
        for(int j=1;j<=sum;j++)
        {
            if(i*prime[j]>N) break;
            not_prime[i*prime[j]]=1;
            if(i%prime[j]) break;
        }
    }
}
int get_phi(int x)//欧拉函数 
{
    int sum=x;
    if(x%2==0)
    {
        while(x%2==0) x/=2;
        sum/=2;
    }
    for(int i=3;i*i<=n;i++)
     if(x%i==0)
     {
         while(x%i==0) x/=i;
         sum=sum/i*(i-1);
     }
    if(x>1) sum=sum/x*(x-1);
    return sum;
}
int GCD(int a,int b)//欧几里得定理 
{
    if(b==0) return a;
    return GCD(b,a%b);
}
int ex_gcd(int a,int b,int &x,int &y)//拓展欧几里得 
{
    if(b==0)
    {
        x=1,y=0;
        return a;
    }
    int r=ex_gcd(b,a%b,x,y),tmp;
    tmp=x,x=y,y=tmp-a/b*y;
    return r;
} 
LL multi(LL a,LL b,int p)//慢速乘 
{
    LL res=1;
    while(b)
    {
        if(b&1) res=(res+a)%p;
        a=a*2%p,b>>=1;
    }
    return res;
}
/*************Lucas定理****************/
LL qpow(LL a,LL b,int p)//快速幂 
{
    LL res=1;
    while(b)
    {
        if(b&1) res=res*a%p;
        a=a*a%p,b>>=1;
    }
    return res;
}
LL jie[N];
int begin(int n)
{
    jie[1]=1;
    for(int i=2;i<=n+m;i++)
     jie[i]=1ll*jie[i-1]*i%mod;
}
LL C(LL n,LL m,LL p)
{
    if(m>n) return 0;
    return jie[n]%p*qpow(1LL*jie[m]*jie[n-m]%p,p-2,p)%p;
}
LL lus(LL n,LL m,LL p)
{
    if(m==0) return 1;
    return C(n%p,m%p,p)*lus(n/p,m/p,p)%p;
}
/*******矩阵乘法加速斐波那契*****************/ 
struct Node
{
    LL m[3][3];
    Node(){memset(m,0,sizeof(m));}
}mb,ans;
Node operator*(Node a,Node b)
{
    Node c;
    for(int i=1;i<=2;i++)
     for(int j=1;j<=2;j++)
      for(int k=1;k<=2;k++)
       c.m[i][j]=(c.m[i][j]%mod+a.m[i][k]*b.m[k][j]%mod)%mod;
    return c;
}
int fei()
{
    n=read(),n--;
    mb.m[1][1]=mb.m[1][2]=mb.m[2][1]=1;
    ans.m[1][1]=ans.m[2][2]=1;
    while(n)
    {
        if(n&1) ans=ans*mb;
        mb=mb*mb;n>>=1;
    }
    cout<<ans.m[1][1];
}
/***************************卡特兰数***************************/
int h[N];
int catelan1()//卡特兰数递推式 
{
    h[0]=h[1]=1;
    for(int i=2;i<=n;i++)
     for(int j=1;j<=i;j++)
      h[i]=h[i-j]*h[j-1]+h[i];
    return h[n];
} 
int len,tmp,a[N][N],b[N];
int catelan2()//高精卡特兰数 
{
    len=1;a[1][0]=b[1]=1;
    for(int i=2;i<110;i++)
    {
        for(int j=0;j<len;j++)
         a[i][j]=a[i-1][j]*(4*i-2);
        sum=0;
        for(int j=0;j<len;j++)
        {
            tmp=sum+a[i][j];
            a[i][j]=tmp%10;
            sum=tmp/10;
        }
        while(sum)
        {
            a[i][len++]=sum%10;
            sum/=10;
        }
        for(int j=len-1;j>=0;j--)
        {
            tmp=10*sum+a[i][j];
            a[i][j]=tmp/(i+1);
            sum=tmp%(i+1);
        }
        while(!a[i][len-1]) len--;
        b[i]=len; 
    }
    for(int i=b[n];i>=0;i--)
     printf("%d",a[n][i]);
    printf("\n");
}
/*****************************************/
int main()
{
    int t=read(),p;
    while(t--) 
    {
        n=read(),m=read(),p=read();
        begin(n+m);
        printf("%lld\n",lus(n+m,m,p));
     } 
    return 0;
}

 

转载于:https://www.cnblogs.com/z360/p/7801508.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值