由于本人当时写下此文时对于STL的用法还不太熟练,现在看来,下文中的自定义的change函数完全可以被替换为reverse函数。
比起用字符串和数组进行高精度, v e c t o r vector vector显得更加的灵活
需要注意的是,高精加法和乘法适合逆序处理,高精除法适合顺序处理,具体情况具体分析
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e4+10;
char as[maxn],bs[maxn];
vector<int>a,b;
int alen,blen;
inline vector<int> change(vector<int>x)//顺序转倒序
{
vector<int>y;
int len=(int)x.size();
for(register int i=len-1;i>=0;i--)
y.push_back(x[i]);
return y;
}
inline int cmp(vector<int>x,vector<int>y)//比较 x<y return -1 x==y return 0 x>y return 1
{
int xlen=(int)x.size(),ylen=(int)y.size();
if(xlen<ylen)
return -1;
if(xlen>ylen)
return 1;
for(register int i=0;i<xlen;i++)
{
if(x[i]<y[i])
return -1;
if(x[i]>y[i])
return 1;
}
return 0;
}
inline void out(vector<int>x)//输出
{
int len=(int)x.size();
for(register int i=0;i<len;i++)
putchar(x[i]+48);
puts("");
}
inline vector<int> plu(vector<int>x,vector<int>y)//高精+高精
{
x=change(x);
y=change(y);
int xlen=(int)x.size(),ylen=(int)y.size(),zlen=max(xlen,ylen)+1;
vector<int>z(zlen);
for(register int i=0;i<zlen;i++)
{
if(i<xlen)
z[i]+=x[i];
if(i<ylen)
z[i]+=y[i];
if(z[i]>9)
{
z[i+1]++;
z[i]-=10;
}
}
while(zlen>1 && !z.back())
{
zlen--;
z.pop_back();
}
return change(z);
}
inline vector<int> minu(vector<int>x,vector<int>y)//高精-高精(x>y)
{
x=change(x);
y=change(y);
int xlen=(int)x.size(),ylen=(int)y.size(),zlen=max(xlen,ylen);
vector<int>z(zlen);
for(register int i=0;i<zlen;i++)
{
z[i]+=x[i];
if(i<ylen)
z[i]-=y[i];
if(z[i]<0)
{
z[i]+=10;
z[i+1]--;
}
}
while(zlen>1 && !z.back())
{
zlen--;
z.pop_back();
}
return change(z);
}
inline void outminu(vector<int>x,vector<int>y)//高精-高精
{
int k=cmp(x,y);
if(!k)
{
puts("0");
return;
}
if(k<0)
{
putchar('-');
swap(x,y);
}
out(minu(x,y));
}
inline vector<int> mult(vector<int>x,vector<int>y)//高精*高精
{
int xlen=(int)x.size(),ylen=(int)y.size(),zlen=xlen+ylen;
vector<int>z(zlen);
x=change(x);
y=change(y);
for(register int i=0;i<xlen;i++)
for(register int j=0;j<ylen;j++)
z[i+j]+=x[i]*y[j];
for(register int i=0;i<zlen;i++)
if(z[i]>9)
{
z[i+1]+=z[i]/10;
z[i]%=10;
}
while(zlen>1 && !z.back())
{
z.pop_back();
zlen--;
}
return change(z);
}
inline vector<int> smult(vector<int>x,int y)//高精*低精
{
x=change(x);
int xlen=(int)x.size();
for(register int i=0;i<xlen;i++)
x[i]*=y;
for(register int i=0;i<xlen-1;i++)
if(x[i]>9)
{
x[i+1]+=x[i]/10;
x[i]%=10;
}
while(x[xlen-1]>9)
{
x.push_back(x[xlen-1]/10);
x[xlen-1]%=10;
xlen++;
}
while(xlen>1 && !x.back())
{
x.pop_back();
xlen--;
}
return change(x);
}
inline void divide(vector<int>x,vector<int>y)//高精/%高精 用压位+二分加快了一点
{
int xlen=(int)x.size();
bool flag=0;
vector<int>div,mod;
for(register int i=0;i<xlen;i++)
{
mod.push_back(x[i]);
if((flag || cmp(mod,y)>=0) && i%7==0)
{
int d=0,l=0,r=10000000;
while(l<=r)
{
int mid=(l+r)>>1;
if(cmp(mod,smult(y,mid))>=0)
{
if(mid>d)
d=mid;
l=mid+1;
}
else
r=mid-1;
}
mod=minu(mod,smult(y,d));
if(!mod[0])
mod.pop_back();
if(flag)
for(register int i=1000000;i;i/=10)
{
div.push_back(d/i);
d%=i;
}
else
{
int len=1,c=d;
while(c)
{
c/=10;
len*=10;
}
for(register int i=len/10;i;i/=10)
{
div.push_back(d/i);
d%=i;
}
}
flag=1;
}
}
int d=0,l=0,r=10000000;
while(l<=r)
{
int mid=(l+r)>>1;
if(cmp(mod,smult(y,mid))>=0)
{
if(mid>d)
d=mid;
l=mid+1;
}
else
r=mid-1;
}
mod=minu(mod,smult(y,d));
if(!mod[0])
mod.pop_back();
int len=1,c=d;
while(c)
{
c/=10;
len*=10;
}
for(register int i=len/10;i;i/=10)
{
div.push_back(d/i);
d%=i;
}
if(div.empty())
div.push_back(0);
out(div);
if(mod.empty())
mod.push_back(0);
out(mod);
}//在本地卡满3s的程序交洛谷竟然只有1.8s,我可能需要一台新电脑
signed main()
{
scanf("%s%s",as+1,bs+1);
alen=strlen(as+1);
blen=strlen(bs+1);
for(register int i=1;i<=alen;i++)
a.push_back(as[i]-48);
for(register int i=1;i<=blen;i++)
b.push_back(bs[i]-48);
out(plu(a,b));
outminu(a,b);
out(mult(a,b));
divide(a,b);
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int maxn=5010;
vector<int>a;
char s[maxn];
int len,b;
inline vector<int> divide(vector<int>x,int y)
{
int len=(int)x.size(),sum=0;
bool flag=0;
vector<int>div;
for(register int i=0;i<len;i++)
{
sum=(sum<<3)+(sum<<1)+x[i];
if(flag || sum>=y)
{
flag=1;
div.push_back(sum/y);
sum%=y;
}
}
if(div.empty())
div.push_back(0);
return div;
}
inline void out(vector<int>x)
{
int len=(int)x.size();
for(register int i=0;i<len;i++)
putchar(x[i]+48);
}
int main()
{
scanf("%s%d",s+1,&b);
len=strlen(s+1);
for(register int i=1;i<=len;i++)
a.push_back(s[i]-48);
out(divide(a,b));
return 0;
}
#include<vector>
#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
vector<int>x,ans;
int a,b,t;
string s;
inline vector<int> divide(vector<int>a,int b,int c)
{
vector<int>d;
d.clear();
int len=a.size(),x=0;
for(register int i=0;i<len;i++)
{
x=x*b+a[i];
if(x>=c || !d.empty())
d.push_back(x/c);
x%=c;
}
if(d.empty())
d.push_back(0);
return d;
}
int main()
{
scanf("%d",&t);
for(register int cas=1;cas<=t;cas++)
{
x.clear();
ans.clear();
scanf("%d%d",&a,&b);
cin>>s;
printf("%d ",a);
cout<<s<<endl;
printf("%d ",b);
int len=s.length();
for(register int i=0;i<len;i++)
x.push_back(s[i]-48-7*(s[i]>='A')-6*(s[i]>='a'));
while(x.size()>1 || x.size()==1 && x[0]!=0)
{
len=x.size();
int sum=0;
for(register int i=0;i<len;i++)
sum=(sum*a%b+x[i]%b)%b;
ans.push_back(sum);
x=divide(x,a,b);
}
if(ans.empty())
ans.push_back(0);
for(register int i=ans.size()-1;i>=0;i--)
putchar(ans[i]+48+7*(ans[i]>9)+6*(ans[i]>35));
puts("\n");
}
return 0;
}
在高精过程中,我们有时会因为位数过多而导致TLE,这时我们就需要压位
关于压位:令 b a s e base base为压的位数, n n n为最大位数,若有高精 × \times ×高精,则 n b a s e × 1 0 2 b a s e \frac{n}{base}\times10^{2base} basen×102base不能超过 l i m lim lim
若 a , b a,b a,b中有 2 2 2个为偶数, a n s = 2 gcd ( a 2 , b 2 ) ans=2\gcd(\frac{a}{2},\frac{b}{2}) ans=2gcd(2a,2b)
若 a , b a,b a,b中有 1 1 1个为偶数, a n s = gcd ( a / 2 , b ) o r gcd ( a , b 2 ) ans=\gcd(a/2,b)or\gcd(a,\frac{b}{2}) ans=gcd(a/2,b)orgcd(a,2b)
若 a , b a,b a,b中有 0 0 0个为偶数, a n s = gcd ( a , a − b ) ans=\gcd(a,a-b) ans=gcd(a,a−b)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e4+10,base=1e7,baselen=7;
char A[maxn],B[maxn];
vector<int>a,b;
inline int pd(vector<int>a,vector<int>b)
{
int lena=a.size(),lenb=b.size();
if(lena<lenb)
return -1;
if(lena>lenb)
return 1;
for(register int i=0;i<lena;i++)
{
if(a[i]<b[i])
return -1;
if(a[i]>b[i])
return 1;
}
return 0;
}
inline void out(vector<int>x)
{
int len=x.size();
printf("%lld",x[0]);
for(register int i=1;i<len;i++)
printf("%0*lld",baselen,x[i]);
}
inline vector<int> change(vector<int>x)
{
vector<int>res;
int len=x.size();
for(register int i=len-1;i>=0;i--)
res.push_back(x[i]);
return res;
}
inline vector<int> Minus(vector<int>a,vector<int>b)
{
a=change(a);
b=change(b);
int alen=a.size(),blen=b.size();
for(register int i=0;i<blen;i++)
a[i]-=b[i];
for(register int i=0;i<alen;i++)
if(a[i]<0)
{
a[i]+=base;
a[i+1]--;
}
while(!a.back() && alen>1)
{
a.pop_back();
alen--;
}
a=change(a);
return a;
}
inline bool odd(vector<int>x)
{
return x.back()&1;
}
inline vector<int> divide(vector<int>a)
{
vector<int>res;
int st=0,len=a.size();
if(a[0]==1)
{
a[1]+=base;
st=1;
}
for(register int i=st;i<len;i++)
{
res.push_back(a[i]>>1);
if(a[i]&1)
a[i+1]+=base;
}
return res;
}
inline vector<int> mult(vector<int>x)
{
x=change(x);
int len=x.size();
for(register int i=0;i<len;i++)
x[i]<<=1;
for(register int i=0;i<len-1;i++)
if(x[i]>=base)
{
x[i+1]++;
x[i]-=base;
}
if(x.back()>=base)
{
x.push_back(1);
x[len-1]-=base;
}
x=change(x);
return x;
}
inline vector<int> times(vector<int>a,vector<int>b)
{
int alen=a.size(),blen=b.size(),clen=alen+blen;
vector<int>c(clen);
a=change(a);
b=change(b);
for(register int i=0;i<alen;i++)
for(register int j=0;j<blen;j++)
c[i+j]+=a[i]*b[j];
for(register int i=0;i<clen;i++)
if(c[i]>=base)
{
c[i+1]+=c[i]/base;
c[i]%=base;
}
while(clen>1 && !c.back())
{
c.pop_back();
clen--;
}
return change(c);
}
inline vector<int> gcd(vector<int>a,vector<int>b)
{
vector<int>s;
s.push_back(1);
for(;;)
{
int k=pd(a,b);
if(k==0)
return times(a,s);
if(k<0)
swap(a,b);
int oa=odd(a),ob=odd(b);
if(oa && ob)
a=Minus(a,b);
if(!oa && ob)
a=divide(a);
if(oa && !ob)
b=divide(b);
if(!oa && !ob)
{
a=divide(a);
b=divide(b);
s=mult(s);
}
}
}
signed main()
{
scanf("%s%s",A+1,B+1);
int len=strlen(A+1);
for(register int i=len,x;i>=1;i-=7)
{
x=0;
for(register int j=max(i-6,1ll);j<=i;j++)
x=x*10+A[j]-48;
a.push_back(x);
}
a=change(a);
len=strlen(B+1);
for(register int i=len,x;i>=1;i-=7)
{
x=0;
for(register int j=max(i-6,1ll);j<=i;j++)
x=x*10+B[j]-48;
b.push_back(x);
}
b=change(b);
out(gcd(a,b));
return 0;
}