常用数论算法

常用数论算法(C++描述) 网上找到的是PASCAL的……于是自己转成C++来写一遍……1.求两数的最小公倍数和最大公约数//(辗转相除法/欧几里德算法)//求两数的最大公约数int gcd(int a,int b)...{    if(b==0)        return a;    else        return gcd(b,a%b);}//扩展:求出gcd(a,b)和满足gcd(a,b)=ax+by 阅读详情

扩展欧几里得:解不定方程,求逆元

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

求ax ≡ 1 (mod n)的乘法逆元,若不存在,返回-1

long long Inverse(long long a,long long n)
{
      long long x,y;
      if(extended_gcd(a,n,x,y)==1)return (x+n)%n; else return -1;
}


欧拉函数:

单个欧拉函数:时间复杂度o(sqrt(n))

int euler(int x)                                //计算φ(x)
{
     int i,ans= x, a = x;                     //找出所有x的质因数
     for(i = 2; i*i<= a; i++)              //从2讨论到sqrt(n)即可
     {
            if(a%i == 0)                       //i为x的质因数
            {
                  ans = ans-ans/i;              //φ(x) = x*(1 - 1/p1)*(1 - 1/p2)......
                  while(a%i == 0) a=a/i;   //算术基本定理,抹掉i^1,i^2,i^3....
            }
     }
     if(a > 1) ans =ans - ans/a;            //存在大于sqrt(a)的质因子
     return ans;
}
线性筛欧拉函数:

void getPhi()
{
	int i,j,tot=0;
	for(i=2;i<=MaxN;i++)              {
		if(Mark[i]==false){  Prime[++tot]=i;  phi[i]=i-1;  }//当 i 是素数时 phi[i]=i-1
		for(j=1; j<=tot&&i*Prime[j]<=MaxN; j++)                           {
			Mark[i*Prime[j]]=true;            
			if(i%Prime[j]==0)                                {   
				phi[i*prime[j]]=phi[i]*prime[j];   break;
			 }            //如果i mod p = 0, 那么 phi[i * p]=p * phi[i] 
			else   phi[i*Prime[j]]=phi[i]*(Prime[j]-1);
		}//其实这里Prime[j]-1就是phi[Prime[j]],利用了欧拉函数的积性  
     	}             
}
既然写到线性筛了,那就写完。

线性筛质数:

void getPrime()
{
       int i,j,tot=0;
       for(i=2;i<=MaxN;i++)
      {
         	if(Mark[i]==false)Prime[++tot]=i;
         	for(j=1; j<=tot&&i*prime[j]<=MaxN; j++)             {
             		Mark[i*Prime[j]]=true;  //Prime[j]是合数i*Prime[j]的最小质因数            
             		if(i%Prime[j]==0) break;  
        	}            // ↑ 比一个合数大的质数和该合数的乘积可用一个更大的合数和比其小的质数相乘得到
     }
}
线性筛一个数的因数个数:

void pre(){
	int i,j; 
	d[1]=1; 
	for(i=2;i<=b;i++){
		if(!mark[i]){prime[++tot]=i;temp[i]=1;d[i]=2;}
		for(j=1;j<=tot&&i*prime[j]<=b;j++){
			mark[i*prime[j]]=true;
			if(i%prime[j]==0){
				d[i*prime[j]]=d[i]/(temp[i]+1)*(temp[i]+2);
				temp[i*prime[j]]=temp[i]+1;
				break;
			}
			else{
				d[i*prime[j]]=d[i]*d[prime[j]];
				temp[i*prime[j]]=1;
			} 
		}
	}
}

二分快速幂:x^y%z;

long long mont(long long x,long long y,long long z){
	long long temp=1;
	for(x%=z;y;y>>=1,x=(x*x)%z){
		if(y&1)temp=(temp*x)%z;
	}
	return temp;
}
矩阵乘法模板:

#include<cstdio> 
#include<iostream> 
#include<algorithm> 
#include<cstdlib> 
#include<cstring> 
#define mod m 
using namespace std; 
typedef long long arr[10][10]; 
arr a,b,z,ans,map; 
long long n,m; 
void multiply(arr x,arr y){ 
    memset(z,0,sizeof(z)); 
    for(long long i=1;i<=5;i++){ 
        for(long long j=1;j<=5;j++){ 
            for(long long h=1;h<=5;h++){ 
                z[i][j]=(z[i][j]+x[i][h]*y[h][j]%mod)%mod; 
            } 
        } 
    } 
    memcpy(x,z,sizeof(z)); 
} 
void mont(long long t){ 
    memset(ans,0,sizeof(ans)); 
    for(long long i=1;i<=5;i++)ans[i][i]=1; 
    while(t>0){ 
        if(t&1)multiply(ans,b); 
        t>>=1; 
        multiply(b,b); 
    } 
} 
int main(){ 
    long long i,j; 
    scanf("%I64d%I64d",&n,&m); 
    if(n==1){ 
        cout<<"2";return 0; 
    } 
    if(n==2){ 
        cout<<"5";return 0; 
    } 
	b[1][5]=1;
	b[2][2]=1;
	b[2][5]=2;
	b[3][4]=b[3][5]=1;
	b[4][3]=1;
	b[5][1]=b[5][2]=b[5][3]=b[5][5]=1;
	a[1][1]=1;
	a[1][2]=2;
	a[1][3]=1;
	a[1][4]=1;
	a[1][5]=5;
    mont(n-2); 
    multiply(a,ans); 
    cout<<a[1][5];
}
关于杨辉三角和组合数:

单个:

long long C(long long n,long long m){
	int i,j;
	a=1;
	b=1;
	if(m>n/2)m=n-m;
	for(i=n,j=1;j<=m;i--,j++){
		a*=i;
		b*=j;
		if(a%b==0){
			a/=b;
			b=1;
		}
	}
	return a/b;
}

一排:组合数取模o(nlogn)

zuhe[0]=1;
zuhe[1]=t;
for(i=2;i<t;i++){
	long long x,y,a,b;
	long long niyuan=mont(i,mod-2,mod);
	zuhe[i]=zuhe[i-1]*niyuan%mod*(t-i+1)%mod;
}
zuhe[t]=1;
还有一种,先预处理1--t的阶乘,直接弄,当然也要求逆元!o(nlongn)


线性筛质因数个数(重复的算多个):

for(i=2;i<=maxm;i++){
        if(sum[i]==0){
        	prime[++tot]=i;
			sum[i]=1;
		}
        for(j=1;j<=tot&&i*prime[j]<=maxm;j++){
            sum[i*prime[j]]=sum[i]+1;
            if((i%prime[j])==0)break;
        }


线性筛莫比乌斯函数:

void pre(){
	int i,j;
	mobius[1]=1;
	for(i=2;i<=50000;i++){
		if(mark[i]==false){
			prime[++tot]=i;
			mobius[i]=-1;
		}
		for(j=1;j<=tot&&i*prime[j]<=50000;j++){
			mark[i*prime[j]]=true;
			if(i%prime[j]==0){
				mobius[i*prime[j]]=0;
				break;
			}
			mobius[i*prime[j]]=-mobius[i];
		}
	}
}



数论算法 数论而已,供大家学习参考借鉴 立即下载

相关推荐

[算法数论].裴定一.清晰版.pdf

内容简介: 本书论述了算法数论的基本内容,其中包括:连分数、代数数域、椭圆曲线、素性检验、大整数因子分解算法、椭圆曲线上的离散对数、超椭圆曲线。本书的特点是内容涉及面广,在有限的篇幅内,包含了必要的预备知识和数学证明,尽可能形成一个完整的体系。并且本书的部分内容曾多次在中国科学院研究生院信息安全国家重点实验室和广州大学作为硕士研究生教材使用。本书可作为信息安全、数论等专业的研究生教材及相关专业的研究人员、高等学校的教师和高年级学生的参考。 目录: 序 前言 第一章 整数的因子分解 1.1 唯一分解定理 1.2 辗转相除法(欧氏除法) 1.3 Mersenne素数和Fermat素数 1.4 整系数多项式 1.5 环Z和Z[ω] 习题一 第二章 同余式 2.1 孙子定理 2.2 剩余类环 2.3 Euler函数ρ(m) 2.4 同余方程 2.5 原根 2.6 缩系的构造 习题二 第三章 二次剩余 3.1 定义及Euler判别条件 3.2 Legendre符号 3.3 Jacobi符号 习题三 第四章 特征 4.1 剩余系的表示 4.2 特征 4.3 原特征 4.4 特征和 4.5 Gauss和 习题四 第五章 连分数 5.1 简单连分数 5.2 用连分数表实数 5.3 最佳渐近分数 5.4 Legendre判别条件 习题五 第六章 代数数域 6.1 代数整数 6.2 Dedekind整环 6.3 阶的一些性质 第七章 椭圆曲线 7.1 椭圆曲线的群结构 7.2 除子类群 7.3 同种映射 7.4 Tate模和Weil对 7.5 有限域上的椭圆曲线 习题七 第八章 在密码学中的一些应用 8.1 RSA公钥密码 8.2 Uiffie-Hellman体制 8.3 ElGamal算法 8.4 基于背包问题的公钥密码 8.5 秘密共享 第九章 素性检验 9.1 Fermat小定理及伪素数 9.2 强伪素数及Miller-Rabin检验 9.3 利用n-1的因子分解的素性检验 9.4 利用n+1的因子分解的素性检验 9.5 分圆环素性检验 9.6 基于椭圆曲线的素性检验 第十章 大整数因子分解算法 10.1 连分数因子分解算法 10.2 二次筛法 10.3 Pollard的P-1因子分解算法 10.4 椭圆曲线因子分解算法 10.5 数域筛法 习题十 第十一章 椭圆曲线上的离散对数 11.1 椭圆曲线公钥密码 11.2 小步-大步法 11.3 家袋鼠和野袋鼠 11.4 MOV约化 11.5 FR约化 11.6 SSSA约化 11.7 有限域上离散对数的计算 第十二章 超椭圆曲线 12.1 超椭圆曲线的Jacobian 12.2 虚二次代数函数域 12.3 基于超椭圆曲线的公钥密码 附录 一些常用算法 A.1 不可约多项式的判别 A.2 有限域中平方根的求解 A.3 有限域上的分解 A.4 Hensel引理 A.5 格 A.6 Z[x]中多项式的分解 参考文献 免责申明:此书是我在网络上获取的,希望对大家有用。资源版权归作者及其公司所有,如果你喜欢,请购买正版。~~~

常用数论算法

素数晒,欧拉函数,快速幂,逆元,组合数

No smile博客 2191

数论基本算法 数论 基本算法系列

这是基本数论也就是初等数论算法系列的一个集合,其中包括可除性 素数 公约数 等等一些基本数论内容 内容短 但很精悍 值得推荐

常见的数论算法

常见的数论算法

Joseph Wen的博客 976

数论算法详解

数论算法详解 视频教程

zgwzgw的博客 223

几个常用数论算法

1、辗转相除法     也许这是最广为人知的数论算法了。

童凌的技术博客 2679

算法 | 数论

基础 同余定理 Lucas(卢卡斯)定理 【数论】 等差数列和等比数列公式 斯特林公式 (Stirling公式) 筛选法 数论 51Nod_1058 N的阶乘的长度 高斯消元法 L1-006 连续因子【枚举】 51Nod_1414 冰雕【模拟+枚举】 51Nod_1035 最长的循环节【数论】 【2016 CCPC 网络赛 】A A water problem 51Nod...

逐梦者 833

算法模板——常用数论算法

目录欧几里得算法快速幂算法 欧几里得算法 求两个整数的最大公约数,时间复杂度O(logn) int gcd(int a, int b) { return b ? gcd(b, a % b) : a; } 快速幂算法 快速求a的b次方 typedef long long ll; ll quick_pow(const ll a, const ll b) { ll result = 1, ans = a; while (b) { // 如果b是奇数,结果乘一次底数 if (b &amp

兮杰 362

算法常用的基础数论

常用的基础数论:最大公约数和最小公倍数、高效判断素数、找质因子

指针不指南吗的博客 1625

常用数论算法板子

常用数论算法 # include &lt;cstdio&gt; # include &lt;cstring&gt; # include &lt;algorithm&gt; # include &lt;queue&gt; # include &lt;map&gt; # define ll long long using namespace std; const int maxn = 1e6...

AC即性感 458

常用数论算法模板

参考文献:acwing 欧几里得算法 int gcd(int a, int b) // 欧几里得算法 { return b ? gcd(b, a % b) : a; } 扩展欧几里得算法, 求x, y,使得ax + by = gcd(a, b) int exgcd(int a, int b, int &x, int &y) // 扩展欧几里得算法, 求x, y,使得ax + by = gcd(a, b) { if (!b) { x = 1

weixin_51008024的博客 191

Ellipse类中常用功能,数论中的常用算法实现

本文中截图来自于《SM2椭圆曲线公钥密码算法》,如有需要,请联系我,源码Utils.java也上传至github,如有需要,也请联系我。 package cn.com.shfe.sfit.dong; import java.util.ArrayList; import java.util.List; /** * @ClassName: Utils * @Descr...

发表于董的博客,gentledongyanchao 628

算法常用数论(一)

(一):欧几里得算法 用来求最大公约数,又叫辗转相除法, int gcd(int a,int b) { return b==0?b:gcd(b,a%b); } (二): 费马小定理 在用快速幂,除法取模时会用到。 当p是素数的时候,如果gcd(a,b)=1;两边同时mod p,当除一个数取模时需要用逆元,不然会产生误差, 更具逆元的特性,a*X=1;X...

qq_40934440的博客 607

数论中的常用算法模板

辗转相除法(欧几里得)求a,b的最大公约数int gcd(int a,int b){ return b==0?a:gcd(b,a%b);}线性筛选法找出素数#define N 100005using namespace std;int cnt,p[N];//p素组中记录了每一个素数bool tag[N];//tag标记i是否为素数,true为素数,初始化时都为truevoid get_prime(

Nature_Ran的专栏 377

算法竞赛-训练指南》第二章-数论常用算法总结

数论是一个神奇的东西,各种结论都很经典,有些懂,有些自己还不是很懂。 接下来就一个一个的介绍吧。 第一、素数,素数本身就是一个很让人惊奇的数,因为它代表的是唯一,自己就有连个因数,一个是1,一个是自己,因为1是每个数都具备的因子(除了0),所以,它也就相当于只有自己。是一个自我感觉很良好的人呀! 最朴素的算法当然是从2-sqrt(2)里面找因子,如果没有,就说明它是个素数。为什么到sqrt(

李硕 1246

算法题中常用数学概念、公式、方法汇总(其三:数论

60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁。所谓质数筛,指的是类似筛子一样,可以高效地把合数过滤掉,留下质数。每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!为了避免同一个合数被重复筛选,对于每一个合数,我们希望只它被其最小的质因数筛选。多数情况下,更易于理解的埃氏筛已经足够优秀了,大家可以只掌握埃氏筛的方法。所以欧拉筛的时间复杂度为。

weixin_48157259的博客 1582
上一篇: 比赛经验总结--187
下一篇: 常用图论算法
INCINCIBLE
博客等级 码龄11年 31粉丝 195原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值