目录
高精度介绍
高精度算法主要用于处理大型数据,其基本原理是通过数组来存储数据,通过对其数组元素进行操作来实现整体的加减乘除。
一、高精度加
只需要开辟一个数组来存储,即 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++;
}
}