高精度、快速幂与快速排序

目录

高精度介绍

一、高精度加

二、高精度减

三、高精度乘

1.高精乘单精

2.高精乘高精

四、高精度除

快速幂介绍

一、快速幂取模

快速排序介绍

一、快速排序

综合


高精度介绍

高精度算法主要用于处理大型数据,其基本原理是通过数组来存储数据,通过对其数组元素进行操作来实现整体的加减乘除。

一、高精度加

只需要开辟一个数组来存储,即  c[i]=a[i]+b[i]+x,  x为低位的进位,然后  x=c[i]/10;  c[i]%=10;即可。

#include <bits/stdc++.h>
using namespace std;
string n,m;
int a[520],b[520],c[520];
int main() {
   cin>>a>>b;
    int la=n.size(),lb=m.size();
    for(int i=1;i<=la;i++)a[i]=n[la-i]-48;    //倒置 
    for(int i=1;i<=lb;i++)b[i]=m[lb-i]-48;
      
    int x=0,lc=1;                             //x为进位 
    while(la>=lc||lb>=lc)
    {
	c[lc]+=at[lc]+bt[lc]+x;
	x=c[lc]/10;
	c[lc]%=10;
	lc++;
	}
	c[lc]=x;                     //最后一个进位补上
	if(c[lc]==0)                 //可能没有进位 
	lc--;
	  
	for(int i=lc;i>=1;i--)
	cout<<c[i];
	  
}

P1601 A+B Problem(高精) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

二、高精度减

类似加法,但有补位的情况,还需注意负数结果。

#include<bits/stdc++.h>
using namespace std;
int a[101000],b[101000],c[101000];
char n1[101000],n2[101000],t[101000];
int la, lb, lc,flag=0;
int main() {
    cin >> n1 >> n2;
    la=strlen(n1),lb=strlen(n2);

    if(lb>la||strcmp(n1,n2)<0&&la==lb)        //若n2大于n1,则交换字符串
    {
 	flag=1;
 	strcpy(t,n1);
 	strcpy(n1,n2);
 	strcpy(n2,t);
 	la=strlen(n1);
 	lb=strlen(n2);
    }
    
    for(int i=0; i<la; i++) a[la - i] =n1[i]-48;
    for(int i=0; i<lb; i++) b[lb - i] =n2[i]-48;
    lc = 1;
    while(lc<=la||lc<=lb) 
   {
        if(a[lc] < b[lc])              //不足补零
		{
            c[lc] = a[lc] + 10 - b[lc];
            a[lc+1]--;
        }
        else
            c[lc] = a[lc] - b[lc]; 
        lc++;
    }

    while(c[lc] == 0 && lc > 1)      //清除前导零
         lc--;
         if(flag)
         cout<<'-';
    for(int i=lc; i>=1; i--)cout << c[i];
 
    return 0;
}

P2142 高精度减法 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

三、高精度乘

1.高精乘单精

将单精乘以高精度的每一位,注意最高位进位可能不止进一位。


#include<iostream>
#include <bits/stdc++.h>
#include<algorithm>
using namespace std;
int s[10000];
int n;
int t,ans=0,num;
int main() {
	cin >> t;
	while(t--)
	{
		cin>>n;
		s[1]=1;
     	int	p=1,jw=0,j;    //p代表位数,jw代表进位 
		for(int i=2;i<=n;i++)
		{

		   for(j=1;j<=p;j++)  
		   {
		   s[j]=s[j]*i+jw;
		   jw=s[j]/10;
		   s[j]%=10;
		   }
           
           while(jw>0)   //若还有进位,则处理进位 
		   {
		   	s[j]=jw%10;
		   	jw/=10;
		   	j++;
		   }
		   p=j-1;    //位数等于j-1 
		   
		}
		
	}

}

P1591 阶乘数码 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

2.高精乘高精

高精乘高精套用公式  c[i+j-1]=c[i+j-1]+a[i]*b[j]+x  (x为进位),i+lb位是最高位进位,积长度最长为两因子长度相加。


#include<iostream>
#include <bits/stdc++.h>
#include<algorithm>
using namespace std;
string at,bt;
int a[2005],b[2005],c[4000005];

int main() {
   cin>>at>>bt;
   int la=at.size(),lb=bt.size();
   for(int i=1;i<=la;i++)a[i]=at[la-i]-48;
   for(int i=1;i<=lb;i++)b[i]=bt[lb-i]-48;
      int x=0,lc=1;
    
    for(int i=1;i<=la;i++)
    {
		x=0;
		for(int j=1;j<=lb;j++)
		{
			c[i+j-1]=c[i+j-1]+x+a[i]*b[j];
			x=c[i+j-1]/10;
			c[i+j-1]%=10;
			
		}
		c[i+lb]=x;
	}

	lc=la+lb;
	while(c[lc]==0&&lc>1)
	lc--;
	  for(int i=lc;i>=1;i--)
	  cout<<c[i];
	  return 0;
}

P1303 A*B Problem - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

四、高精度除

将被除数的每一位加上上一位的余数(余数需要乘10)除以除数,即   c[i]=(a[i]+x*10)/b   ,高精除单精不需要倒序。

#include<bits/stdc++.h>
using namespace std;
int t;
int n;
char s[5005];
int a[5005],b,c[5005];
int main() {

    cin>>s>>b;
    int la=strlen(s);
    for(int i=1;i<=la;i++)
    a[i]=s[i-1]-48;             //高精除单精不用倒序 
    
    long long x=0;                   //余数 
    for(int i=1;i<=la;i++)
    {
		c[i]=(a[i]+x*10)/b;    
		x=(a[i]+x*10)%b;   
	}
	
	int lc=1;
	while(c[lc]==0&&lc<la)    //清除前置零 
	lc++;
	for(int i=lc;i<=la;i++)
	cout<<c[i];
}

P1480 A/B Problem - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

快速幂介绍

快速幂算法可以快速的算出指数非常大的幂,比单独一个for循环指数 O(n)要快的多,其基本原理如下:

3^10=(3*3)*(3*3)*(3*3)*(3*3)*(3*3)

3^10=9*9*9*9*9=81*81*9=6561*9

每次指数除以2,底数取平方,每次循环的次数都会减半。

一、快速幂取模

此题题目为幂取位数,即取模。  乘法取模公式为  (a*b)%p=(a%p*b%p)%p    

#include <iostream>
using namespace std;
long long  a,b,p;
int main()
{
	cin>>a>>b>>p;
	long long  ans=1,mul=a,index=b;
	while(index>0)
	{
		if(index&1)     //若指数为奇数的话,得先把树枝乘上
		{
			ans*=mul;
			ans%=p;
		}
		index>>=1;
		mul=(mul*mul)%p;     //底数取平方
	}
	ans%=p;
    cout<<a<<'^'<<b<<" mod "<<p<<'='<<ans;
}

P1226 【模板】快速幂 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

快速排序介绍

快速排序的原理是选定一个分界值,将数组中小于分界值的数放在它的右边,大于它的放在左边,再把数组中分界位置分为两个数组,重复上列操作。

一、快速排序

模板。

#include<bits/stdc++.h>
#include <algorithm>
using namespace std;
int n,m;
int a[2000000];
void quicksort(int l,int r)
{
	int i=l,j=r,t=a[l];
	if(i>=j)
	return ;
	
	while(i<j)
	{
		while(a[j]>=t&&i<j)j--;
		while(a[i]<=t&&i<j)i++;
		swap(a[i],a[j]);
	}
	swap(a[l],a[j]);
	quicksort(l,i-1);
	quicksort(i+1,r);
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	std::cin>>a[i];
	quicksort(1,m);
	for(int i=1;i<=m;i++)
	cout<<a[i]<<' ';
}

P1271 【深基9.例1】选举学生会 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

综合

此题为快速幂+高精乘,还需知道2^p的位数为  p*log10(2)+1  

#include<bits/stdc++.h>
#include<cmath>
using namespace std;
typedef long long ll;
int a[1000000],b[1000000],c[1000000];  //a是主因子,b是副因子,c辅助存储 
int p,inde,la=1,lb=1;
void multiply1()
{
	memset(c,0,sizeof c);
	for(int i=1;i<=la;i++)
	{
		int x=0;
		for(int j=1;j<=lb;j++)
		{
			c[i+j-1]+=a[i]*b[j]+x;
			x=c[i+j-1]/10;
			c[i+j-1]%=10;
		}
		c[i+lb]=x;
	}
	int lc=la+lb;
	while(c[lc]==0&&lc>1)
	lc--;
	
	for(int i=1;i<=lc;i++)
	a[i]=c[i];
	la=min(500,lc);
}

void multiply2()
{
	memset(c,0,sizeof c);
	for(int i=1;i<=lb;i++)
	{
		int x=0;
		for(int j=1;j<=lb;j++)
		{
			c[i+j-1]+=b[i]*b[j]+x;
			x=c[i+j-1]/10;
			c[i+j-1]%=10;
		}
		c[i+lb]=x;
	}
	int lc=lb+lb;
	while(c[lc]==0&&lc>1)
	lc--;
	
	for(int i=1;i<=lc;i++)
	b[i]=c[i];
	lb=min(lc,500);
}

void quickM()     //快速幂 
{
	while(inde>0)
	{
		if(inde&1)
		{
			multiply1();   //高精乘 
		}
		inde>>=1;
		multiply2();
	}
}
int main()
{
    cin>>p;
    inde=p;
    cout<<(int)(p*log10(2)+1);    //2^p位数等于10^X=X+1,log10(2^p)=X
	                                    //故X+1等于 log10(2^p)+1
    a[1]=1,b[1]=2;
    quickM();
    a[1]--;
    for(int i=500,j=0;i>=1;i--)
    {
		if(j%50==0)
		cout<<endl;
		cout<<a[i];
		j++;
	}
    	
}

P1045 [NOIP2003 普及组] 麦森数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

  • 17
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
目录 第一章 从零开始 8 1.1机试分析 8 1.2 IDE的选择与评测结果 10 1.3 DreamJudge的使用 11 1.4输入输出技巧 12 1.5头文件技巧 15 1.6数组使用技巧 16 1.7审时度势 — 复杂度与是否可做 19 1.8 C++ STL的使用 21 1.9多组输入的问题 27 第二章 入门经典 29 2.1 简单模拟 30 2.2 进制转换类问题 32 2.3 排版类问题 37 2.4 日期类问题 42 2.5 字符串类问题 45 2.6 排序类问题 47 2.7 查找类问题 54 2.8 贪心类问题 61 2.9 链表类问题 65 第三章 数学 68 3.1 同模余定理 69 3.2 最大公约数(GCD) 72 3.3 最小公倍数(LCM) 74 3.4 斐波那契数列 75 3.5 素数判定 76 3.6 素数筛选 78 3.7 分解素因数 81 3.8 二分快速幂 83 3.9 常见数学公式总结 85 3.10 规律神器OEIS 87 第四章 高精度问题 89 4.1 Python解法 90 4.2 Java解法 91 4.3 C/C++解法 92 第五章 数据结构 93 5.1 栈的应用 94 5.2 哈夫曼树 96 5.3 二叉树 102 5.4 二叉排序树 111 5.5 hash算法 114 5.6 前缀树 115 第六章 搜索 121 6.1 暴力枚举 122 6.2 广度优先搜索(BFS) 124 6.3 递归及其应用 127 6.4 深度优先搜索(DFS) 130 6.5 搜索剪枝技巧 135 6.6 终极骗分技巧 138 第七章 图论 139 7.1 理论基础 140 7.2 图的存储 145 7.3 并查集 148 7.4 最小生成树问题 151 7.5 最短路径问题 155 7.6 拓扑排序 162 第八章 动态规划 165 8.1 递推求解 166 8.2 最大子段和 168 8.3 最长上升子序列(LIS) 170 8.4 最长公共子序列(LCS) 174 8.5 背包类问题 176 8.6 记忆化搜索 179 8.7 字符串相关的动态规划 182
易语言官方支持库以及网上流传的很多模块中的很多命令或数据结构仅仅是实现了功能,但是并不怎么高效,再有就是有人将本来时间复杂度就高的算法使用汇编进行优化,然并卵,O(n^2)的复杂度和O(nlogn)的复杂度根本不是一个数量级的【注:这里的log以2为底数】。 举个例子:对超大数组进行排序,如果你用传统的选择排序(O(n^2))对一个超大数组进行排序,你恐怕得等几分钟,而采用二分思想的快速排序(最坏情况O(nlogn),最好情况O(n)),最好情况只需要很短时间。量化一下,假如数组内有1024个元素,传统的选择排序本来需要1024*1024=1048576次循环,而使用快速排序,最坏情况只需要1024*log1024=10240次,最好情况只需要1024次,节省了大量时间! 那么,作为一位OIer(Olympic in Informatics),决定将易库中没有的算法以及数据结构以此模块作为补充,将时间复杂度优化到最优,使你的程序运行效率更高! 当前已支持算法快速排序、插入排序、堆排序、归并排序、取最大、取最小、向下取整、向上取整、反转字节集、反转文本、反转数组、扩展欧几里得、中国剩余定理、快速幂、线性回归相关、线性规划 当前已支持数据结构:大根堆、小根堆、并查集、Trie、表达式、高精度整数(部分)、线段树、树状数组、栈 当前计划后续版本更新内容:KMP、AC自动机、红黑树、AVL、SBT、Treap、块状数组、Splay、普通二叉查找树、深度搜索框架、广度搜索框架、图论相关(方向:有向图、无向图;类型:邻接表式、邻接矩阵式;包含算法:dijkstra、floyd、SPFA、kruskal、prim、tarjan强连通分量、遍历、求哈密顿环、匈牙利算法求二分图最大匹配、连通性判断) 另外给喜爱算法的人推荐一本书:刘汝佳的《算法竞赛入门经典》,pan.baidu.com/s/1boNjXYv 密码: pr96,不过有一点,这本书不但会从0给你教算法,还会从0给你教C++。与之配套的是跟这个封皮差不多的蓝色封皮的书,里面有更加高深的算法,是这本书的延伸(这个蓝皮的我在网上找不到电子版,网上有的都是旧版,不是新版)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值