![b3bbdc4d7b699eff1b938446651923ca.png](https://img-blog.csdnimg.cn/img_convert/b3bbdc4d7b699eff1b938446651923ca.png)
高精度加法、减法均可以在
Naive的想法1:
既然直接列竖式做除法是
仔细想想,二分一个
哎呀,二分的
Naive的想法2:
既然多项式除法可以做到
不行,两者定义有差异(多项式除法要求余数度数小于被除数而整数要求余数数值上小于被除数)。
正确做法:
二分的问题出在哪里?要求答案达到
我们要求
时间复杂度:
初始时有效位数为1,之后每迭代一次位数翻倍,乘法使用FFT优化后,时间复杂度满足
故
实现细节:
1.为了方便可以将整数转换成多项式
2.类似多项式求逆,每一次计算时只需要取
3.迭代初值在
例:求。
转换问题变成求。先求
,初值设为
,
第一次迭代:![]()
第二次迭代:![]()
第三次迭代:![]()
第四次迭代:![]()
第五次迭代![]()
需要注意的是最后的答案只有一半的位数是正确的,计算答案得到。
下面是NTT实现的高精度除法(答案向下取整)。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#define loop(n,i) for(register int i=1;i<=(n);++i)
#define MAX 500009
#define zxc(x) cerr<<(#x)<<'='<<(x)<<'n'
#define zxcv(x) cerr<<(#x)<<'='<<(x)<<','
#define int long long
#define P 998244353
using namespace std;
inline int icin(){
char c=getchar();int s=0;bool sign=0;
while(!isdigit(c)&&c^'-')c=getchar();
if(c=='-')c=getchar(),sign=1;
while(isdigit(c))s=(s<<1)+(s<<3)+c-'0',c=getchar();
return sign?-s:s;
}
typedef vector<int> Poly;
inline int Quick(int a,int m){int ans=1;for(;m;m>>=1,a=a*a%P) if(m&1) ans=ans*a%P;return ans;}
int R[MAX];
inline void NTT(Poly& a,int x,int type){
int n=1<<x;
for(register int i=0;i<n;++i) if((R[i]=R[i>>1]>>1|(i&1)<<x-1)>i) swap(a[i],a[R[i]]);
for(register int s=1;s<=x;++s){
int len=1<<s,mid=len>>1;
int w=Quick(3,type*(P-1)/len+P-1);
for(register int k=0;k<n;k+=len){
int d=1;
for(register int j=0;j<mid;++j){
int u=a[j+k],v=a[j+k+mid]*d%P;
a[j+k]=(u+v)%P,a[j+k+mid]=(u-v+P)%P;
d=d*w%P;
}
}
}
if(type==-1) for(register int i=0,inv=Quick(n,P-2);i<n;++i) a[i]=a[i]*inv%P;
}
ostream& operator <<(ostream& out,Poly x){for(register int i=0;i<x.size();++i) out<<x[i]<<' ';return out;}
inline int ceilog(int x){int ans=0;while(1<<ans<x)ans++;return ans;}
Poly operator *(Poly A,Poly B){
int deg=A.size()+B.size()-1;
int x=ceilog(deg);
A.resize(1<<x),B.resize(1<<x);
NTT(A,x,1),NTT(B,x,1);
for(register int i=0;i<1<<x;++i) A[i]=A[i]*B[i]%P;
NTT(A,x,-1);
A.resize(deg);
for(register int i=deg-1;i;--i){
A[i-1]+=A[i]/10;
A[i]%=10;
}
return A;
}
inline Poly Inverse(Poly A){
Poly B,C;B.resize(2);B[1]=100/(A[0]*10+(A.size()>1?A[1]:0));
int x=ceilog(A.size())+1;
for(register int s=1;s<=10;++s){//迭代次数
C.resize(1<<s),B.resize(1<<s);
for(register int i=0;i<min(1ll<<s,(int)A.size());++i) C[i]=A[i];
for(register int i=min(1ll<<s,(int)A.size());i<1<<s;++i) C[i]=0;
C=B*C;
for(register int i=1;i<C.size();++i) C[i]=-C[i];
C[0]=2-C[0];
for(register int i=C.size()-1;i;--i){
C[i-1]+=(C[i]-9)/10;
C[i]=(C[i]+10)%10;
}
B=B*C;
B.resize(1<<s);
}
return B;
}
Poly A,B;
int rest;
main(){
char c=getchar();while(!isdigit(c)) c=getchar();
while(isdigit(c)) A.push_back(c-'0'),c=getchar();
rest+=A.size();
c=getchar();while(!isdigit(c)) c=getchar();
while(isdigit(c)) B.push_back(c-'0'),c=getchar();
rest-=B.size();
A=A*Inverse(B);
for(register int i=0;i<=rest;++i) if(!(i==0&&A[i]==0)) cout<<A[i];
cout<<'n';
}