数论算法模板(不定期更新)

/**********/

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdlib>
#include<vector>
#include<stack>
#include<map>
using namespace std;
typedef long long ll;

/***********GCD**********************/

ll gcd(ll a,ll b)
{
    if(b==0)
        return a;
    return gcd(b,a%b);
}

/*************快速乘***************/

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

/*************快速幂**************/

ll pow_mod(ll x,ll n,ll mod)
{
    if(n==1) return x%mod;
    x%=mod;
    ll t=x,res=1;
    while(n)
    {
        if(n&1) res=mult_mod(res,t,mod);
        t=mult_mod(t,t,mod);
        n>>=1;
    }
    return res;
}

/************扩展欧几里德****************/

void extend_gcd(ll a,ll b,ll &x,ll &y)
{
    ll d; //d=gcd(a,b)
    if(b==0)
    {
        x=1,y=0;
        d=a;
    }
    else
    {
        d=extend_gcd(b,a%b,y,x);
        ll xx=x,yy=y;
        x=yy;
        y=xx-(a/b)*yy;
    }
}

/************素数筛法******************/

ll l,u,prime[N];
int tot;
int vis[N],ans[10000005];

void isPrime()
{
    tot=0;
    memset(vis,0,sizeof(vis));
    memset(prime,0,sizeof(prime));
    for(ll i=2;i<N;i++)
    {
        if(!vis[i])
        {
            prime[tot++]=i;
            for(ll j=i*i;j<N;j+=i)
                vis[j]=1;
        }
    }
}

/*********素数判定Miller_Rabin***********/

bool test(ll a,ll n) //Miller_Rabin算法的核心
{
    ll x=n-1,t=0,res,last;
    while((x&1)==0)
    {
        x>>=1;
        t++;
    }
    last=pow_mod(a,x,n);

    for(int i=0;i<t;i++)
    {
        res=pow_mod(last,2,n);
        if(res==1&&last!=1&&last!=n-1)
            return true;
        last=res;
    }
    if(res!=1) return true;
    return false;
}

bool millier_rabin(ll n)
{
    if(n==2) return true;
    if(n==1||(n&1)==0) return false;
    for(int i=0;i<times;i++)
    {
        ll a=rand()%(n-1)+1;
        if(test(a,n))
            return false;
    }
    return true;
}

/*********大数因数分解Pollard_rho*************/

ll pollard_rho(ll x,ll c)
{
    ll x0,y,i=1,k=2;
    x0=rand()%x;
    y=x0;
    while(1)
    {
        i++;
        x0=(mult_mod(x0,x0,x)+c)%x;
        ll d=gcd(y-x0,x);
        if(d>1&&d<x) return d;
        if(y==x0) break;
        if(i==k)
        {
            y=x0;
            k+=k;
        }
    }
    return x;
}

void find_fac(ll n,int c)
{
    if(n==1) return;
    if(millier_rabin(n))
    {
        factor[tot++]=n;
        return;
    }
    ll p=n;
    while(p>=n)
        p=pollard_rho(p,c--);
    find_fac(p,c);
    find_fac(n/p,c);
}

/**********欧拉函数**********************/

int Euler(int n)
{
    int res=n;
    for(int i=2;i*i<=n;i++)
    {
        while(n%i==0)
        {
            n/=i; res-=(res/i);
            while(n%i==0)
                n/=i;
        }
    }
    if(n>1)
       res-=(res/n);
    return res;
}

/**********欧拉函数**************/

int Euler(int n)
{
    int res=n;
    for(int i=2;i*i<=n;i++)
    {
        while(n%i==0)
        {
            n/=i; res-=(res/i);
            while(n%i==0)
                n/=i;
        }
    }
    if(n>1)
       res-=(res/n);
    return res;
}

/******素数筛法+欧拉打表**********/

ll e[N+5],p[N+5];
bool vis[N+5];

void init()
{
    memset(e,0,sizeof(e));
    memset(p,0,sizeof(p));
    memset(vis,false,sizeof(vis));
    ll i,j;
    p[0]=1;//记录素数总个数
    p[1]=2;

    for(i=3;i<N;i+=2)
    {
        if(!vis[i])
        {
            p[++p[0]]=i;
            for(j=i*i;j<N;j+=i)
                vis[j]=true;
        }
    }

    e[1]=1;
    for(i=1;i<=p[0];i++)
        e[p[i]]=p[i]-1; //为什么要-1?

    for(i=2;i<N;i++)
    {
        if(!e[i])
        {
            for(j=1;j<=p[0];j++)
            {
                if(i%p[j]==0)
                {
                    if(i/p[j]%p[j])
                        e[i]=e[i/p[j]]*e[p[j]];
                    else
                        e[i]=e[i/p[j]]*p[j];
                    break;
                }
            }
        }
    }
}

/*************欧拉打表*更快版***************/

#define N 1000000

int e[N+5];
void init()
{
    int i,j;
    memset(e,0,sizeof(e));
    for(i=2;i<=N;i++)
    {
        if(!e[i])
        {
            for(j=i;j<=N;j+=i)
            {
                if(!e[j])
                    e[j]=j;
                e[j]=e[j]/i*(i-1);
            }
        }
    }
}
时间: 2025-01-04 14:58:27

数论算法模板(不定期更新)的相关文章

数论算法模板总结

公约数 GCD LL GCD( LL a,LL b ) { return b==0?a:GCD(b,a%b); } EX_GCD LL EX_GCD( LL a,LL b,LL &x,LL &y )//ax+by=gcd(a,b) { LL d=a; if( !b ) x=1;y=0; else { d=EX_GCD(b,a%b,y,x); y-=a/b*x; } return d;//返回最大公因数 } /* 求a * x + b * y = c的整数解. 1.先计算Gcd(a,b),若

常用算法设计和优化策略(本蒟蒻不定期更新)

常用算法设计和优化策略(本蒟蒻不定期更新) 下面是紫书上讲的常用算法设计策略和优化策略: 分治法:将问题分成相同的独立子问题求解.拆分出的问题必须有最优子结构性质(子问题求出的是最优解) 动态规划.本质是:对于一个问题,通过划分阶段,定义状态与状态间的关系,来分解问题.利用单阶段问题之间的联系,或者同一阶段状态之间的联系,一个一个阶段往下决策,最终解决问题. 拆分出的问题必须满足最优子结构性质和无后效性(当前阶段以前的状态不会影响以后的状态,只与当前阶段有关).动归的目的是避免重叠子问题.递推和

算法模板学习专栏之总览(会慢慢陆续更新ing)

博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/7495310.html特别不喜欢那些随便转载别人的原创文章又不给出链接的所以不准偷偷复制博主的博客噢~~ 数据结构和算法模板系列之总览 很早前就打算将自己学过的数据结构和算法等知识和模板做个整理,但一直没有抽出时间来弄.现在打算每周抽空一点时间陆陆续续地将自己平时用的模板都贴上来,这里先做个综述. 主要针对那些想要准备机试.刷题或者刚刚接触ACM的初学者来说,对

Floyd判最小环算法模板

算法思想:如果存在最小环,会在编号最大的点u更新最短路径前找到这个环,发现的方法是,更新最短路径前,遍历i,j点对,一定会发现某对i到j的最短路径长度dis[i][j]+mp[j][u]+mp[u][i] != INF,这时i,j是图中挨着u的两个点,因为在之前最短路更新过程中,u没有参与更新,所以dis[i][j]所表示的路径中不会出现u,如果成立,则一定是一个环.用Floyd算法来实现.但是对于负环此算法失效,因为有负环时,dis[i][j]已经不能保证i到j的路径上不会经过同一个点多次了.

node.js项目开发问题集锦(不定期更新,随时把开发过程中遇到的问题加上)

1.用express开发站点时,怎么定义通用的头部和尾部 方案1:用类似asp时代的include添加,如ejs模板: <% include ../header.ejs %> <h1 class="page-header"> 这里是内容. 注:..表示header.ejs在上一级目录,ejs扩展名可以去掉,直接写:include ../header </h1> <% include ../footer %> 方案2:用类似于MVC的lay

Floyd算法模板

Floyd可以求出任意两点间的最短距离,代码也相对简单,对于稀疏图来说效率也还是不错的,但由于三个for循环导致时间复杂度较高,不适合稠密图. Floyd算法模板(精简版): void Floyd() { int dist[maxn][maxn]; // dist存储i到j的最短距离 for(int k = 1; k <= n; k++) for(int i = 1;i <= n; i++) for(int j = 1; j <= n; j++) if(dist[i][k] + dist

【不定期更新】noip复习(或许有误请指正)

一.基本算法 2.二分查找 void find(int l,int r){ if (l>r || a[l]>x || a[r]<x) return; int mid = (l+r) >> 1; if (a[mid] == x){ if (mid < pos)pos=mid; if (a[mid-1] == x) find(l, mid-1); if (a[mid+1] == x) find(mid+1, r); return; } if (x > a[mid])

从壹开始前后端分离 [.netCore 不定期更新 ] 三十五║ 完美实现全局异常日志记录

缘起 哈喽我是不定期更新的日常,昨天群里小伙伴问到了记录日志,当然,以前我也挖过这个坑,后来一直没有来得及填上,也想着 swagger 一直又有错误信息展示的功能,就迟迟没有添加这个功能,不过昨天夜里想了想,还是需要增加上,旨在提高框架的高效性.不定期日常就直接上代码了,我有一个小想法,就是希望大家有好的想法,可以给我说,我会整理下,添加到框架里,并在文章头里写上 投稿作者:这里重点说明下,是参考群里小伙伴 Hello World! 的相关内容,并在他的基础上更新,添加了注入和全局,大家可以看看

二分——二分查找算法模板

转自:二分查找算法模板 二分模板一共有两个,分别适用于不同情况.算法思路:假设目标值在闭区间[l, r]中, 每次将区间长度缩小一半,当l = r时,我们就找到了目标值. 版本1当我们将区间[l, r]划分成[l, mid]和[mid + 1, r]时,其更新操作是r = mid或者l = mid + 1;,计算mid时不需要加1. C++ 代码模板: int bsearch_1(int l, int r) { while (l < r) { int mid = l + r >> 1;